2012-09-22 16 views
11

की लंबाई स्ट्रिंग शाब्दिक संकेत की एक सरणी को देखते हुए निर्धारण:एक स्ट्रिंग शाब्दिक

char *textMessages[] = { 
    "Small text message", 
    "Slightly larger text message", 
    "A really large text message that " 
    "is spread over multiple lines" 
} 

एक एक विशेष स्ट्रिंग शाब्दिक की लंबाई कैसे निर्धारित करता है - तीसरा कहा? मैं sizeof आदेश का उपयोग इस प्रकार की कोशिश की है:

int size = sizeof(textMessages[2]); 

लेकिन परिणाम स्ट्रिंग शाब्दिक की लंबाई सरणी में संकेत की संख्या के बजाय हो रहा है।

+3

'आकार (टेक्स्टमेजेज [2]) '' char * 'प्रकार का आकार उपज करेगा। यह पूरी तरह से संयोग है कि 'आकार (char *)' आपके सिस्टम पर 4 होता है, और आपके सरणी में तत्वों की संख्या के साथ कुछ भी नहीं करना है। –

+0

आपको अपनी सरणी के लिए 'स्थिर कॉन्स चार टेक्स्ट मैसेजेज [] [4]' परिभाषा का उपयोग करने पर विचार करना चाहिए। –

+1

@MichaelFoukarakis सरणी में केवल * तीन * पॉइंटर्स हैं (स्ट्रिंग concatenation नोट करें)। – Jens

उत्तर

17

आप संख्या संकलन समय (के रूप में strlen साथ रनटाइम पर के खिलाफ) पर संगणित चाहते हैं ऐसा लगता है जैसे एक अभिव्यक्ति का उपयोग करने के लिए पूरी तरह से ठीक है

sizeof "A really large text message that " 
     "is spread over multiple lines"; 

आप लंबे समय तक दोहराने से बचने के लिए मैक्रो का उपयोग करना चाहेंगे, हालांकि:

#define LONGLITERAL "A really large text message that " \ 
        "is spread over multiple lines" 

ध्यान दें कि sizeof द्वारा लौटाए गए मान में एनयूएल समाप्ति शामिल है, इसलिए strlen से अधिक एक है।

+0

मैं प्रत्येक स्ट्रिंग की लंबाई निर्धारित करना चाहता हूं ताकि मैं लंबाई को अनुक्रमित कर सकूं और उन्हें किसी फ़ंक्शन में पास कर सकूं। संकलन समय पर इस तरह की लंबाई की गणना करना संभव है? – Zack

+1

मेरा दृष्टिकोण 'struct {char * ptr की सरणी घोषित करना और आरंभ करना होगा; size_t लेन; } एक्स [] '। फिर आप 'foo (x [i] .ptr, x [i] .len) कॉल कर सकते हैं। चूंकि सी स्ट्रिंग की लंबाई को चारों ओर नहीं रखता है, इसलिए आपके कोड में स्ट्रिंग लम्बाई का ट्रैक रखने के अलावा कोई अन्य तरीका नहीं है। – Jens

0

strlen शायद?

size_t size = strlen(textMessages[2]); 
+3

इस नंबर को रनटाइम पर क्यों गणना करें जब इसे संकलित समय पर निर्धारित किया जा सके? – Jens

+0

@ जेन्स: जब तक आप संकलन समय पर स्ट्रिंग को भी नहीं जानते हैं। – Tudor

+0

@ ट्यूडर, हाँ - आप _do_ संकलन समय पर लंबाई जानते हैं (सवाल कहता है "स्ट्रिंग लिटल") – ideasman42

0

आप एक स्ट्रिंग की लंबाई प्राप्त करने के लिए strlen() पुस्तकालय विधि का उपयोग करना चाहिए। sizeof आपको textMessages[2] का आकार देगा, जो एक सूचक है, जो मशीन निर्भर (4 बाइट्स या 8 बाइट्स) होगा।

+0

क्या आपका मतलब 4 या 8 बाइट्स नहीं है? जब तक आपके पास 16-बिट मशीन न हो ... – Tudor

+0

सही, सही करने के लिए धन्यवाद :) – Vikdor

0

strlen जबकि sizeof की डाटा बाइट्स में टाइप करें आप पैरामीटर के रूप में दर्ज किया है आकार वापस आ जाएगी आप स्ट्रिंग की लंबाई देता है।

strlen

sizeof

-1

मैं आपको कुछ बता दूंगा, मेरे ज्ञान सरणी के अनुसार एक पॉइंटर्स को छोड़कर sizeof का उपयोग करते हैं।

जब आप एक सूचक पर sizeof का उपयोग यह हमेशा 4 बाइट परवाह किए बिना बात यह है कि सूचक अंक के लिए, लेकिन अगर यह सरणी पर इस्तेमाल किया यह वापस आ जाएगी कब तक सरणी बाइट में बड़ा है वापस आ जाएगी?

आप उदाहरण में यहाँ *textMessage[] सूचक की सरणी इसलिए जब आप sizeof(textMessage[2]) का उपयोग यह 4 बाइट क्योंकि textMessage[2] एक सूचक है वापस आ जाएगी है।

मुझे आशा है कि यह आपके लिए उपयोगी होगा।

+0

मुझे समझ में नहीं आया कि आप क्या चाहते हैं –

+0

मेरा इरादा आपको http://c-faq.com/aryptr/index.html को पढ़कर सरणी और पॉइंटर्स के ** अंतर ** पर अपना ज्ञान सुधारने के लिए बताना था। Arrays पॉइंटर्स नहीं हैं और वे अक्सर 4 बाइट्स के बजाय 2 या 8 होते हैं और उनका आकार भी इस बात पर निर्भर हो सकता है कि वे किस प्रकार इंगित करते हैं। तो, आपने जो कुछ लिखा है वह तकनीकी रूप से गलत है। – Jens

+0

ठीक है धन्यवाद @ जेन्स –

0

आप इस तथ्य का फायदा उठाने सकता है, कि एक सरणी में मानों लगातार कर रहे हैं:

const char *messages[] = { 
    "footer", 
    "barter", 
    "banger" 
}; 

size_t sizeOfMessage1 = (messages[1] - messages[0])/sizeof(char); // 7 (6 chars + '\0') 

आकार तत्वों की सीमाओं का उपयोग करके निर्धारित किया जाता है।पहले तत्व की शुरुआत और दूसरी तत्व की शुरुआत के बीच की जगह पहले का आकार है।

इसमें \0 समाप्ति शामिल है। समाधान, ज़ाहिर है, लगातार तारों के साथ ठीक से काम करता है। यदि स्ट्रिंग पॉइंटर्स होंगी, तो आपको स्ट्रिंग की लंबाई के बजाय पॉइंटर का आकार मिल जाएगा।

यह काम करने की गारंटी नहीं है। यदि फ़ील्ड गठबंधन होते हैं, तो यह गलत आकार उत्पन्न कर सकता है और कंपाइलर द्वारा पेश की जाने वाली अन्य चेतावनी भी हो सकती हैं, जैसे समान स्ट्रिंग विलय करना। इसके अलावा आपको अपने सरणी में कम से कम दो तत्वों की आवश्यकता होगी।

+3

यह काम करने की गारंटी नहीं है। जबकि सरणी में पॉइंटर्स लगातार होना चाहिए, स्ट्रिंग अक्षर की आवश्यकता नहीं है। संरेखण और इस तरह के बारे में सोचो। या समान स्ट्रिंग अक्षर के लिए एक ही सूचक का उपयोग करना। – Jens

+0

आप सही हैं, संरेखण इसे तोड़ देगा (लेकिन यह नियंत्रित है)। 'Char' के लिए अलग-अलग आकार भी इसे तोड़ देंगे। मैं अपना जवाब विश्वसनीय नहीं मानूंगा। – nemo

+1

समान तारों को विलय करना, एक सामान्य अनुकूलन, इसे भी तोड़ देता है। – Jens

11

मेरा सुझाव strlen का उपयोग करना होगा और संकलक अनुकूलन चालू करना होगा।

86 पर

उदाहरण के लिए, जीसीसी 4.7 के साथ:

#include <string.h> 
static const char *textMessages[3] = { 
    "Small text message", 
    "Slightly larger text message", 
    "A really large text message that " 
    "is spread over multiple lines" 
}; 

size_t longmessagelen(void) 
{ 
    return strlen(textMessages[2]); 
} 

make CFLAGS="-ggdb -O3" example.o चलाने के बाद:

$ gdb example.o 
(gdb) disassemble longmessagelen 
    0x00000000 <+0>: mov $0x3e,%eax 
    0x00000005 <+5>: ret 

अर्थात कंपाइलर ने निरंतर मान 0x3e = 62 के साथ strlen पर कॉल को प्रतिस्थापित कर दिया है।

संकलक अनुकूलन करने में समय बर्बाद न करें जो संकलक आपके लिए कर सकता है!

संबंधित मुद्दे