字符指针取什么地址

时间:2014-09-10 00:43:00

标签: c

我读到了:

char a[] = "string"; 

a: "string"

,而

char *ptr = "string" 

ptr: [__] ---> "string"

我很困惑。我知道的一件事是指针总是存储地址。在字符指针的情况下它存储了什么地址?这个块代表什么(我指向字符串的块)。它是“字符串”的起始地址。

如果是阵列?如何清楚地区分char指针和char数组?

7 个答案:

答案 0 :(得分:5)

图表可能有所帮助。

char *ptr = "string";

+-------+          +----------------------------+
|  ptr  |--------->| s | t | r | i | n | g | \0 |
+-------+          +----------------------------+

char a[] = "string";

+----------------------------+
| s | t | r | i | n | g | \0 |
+----------------------------+

这里,ptr是一个变量,它包含指向某些(常量)数据的指针。您可以随后通过为ptr分配新值来更改其指向的内存地址,例如ptr = "alternative"; - 但您无法合法地更改持有"string"的数组的内容(它是正式只读或const,并尝试修改它可能会使程序崩溃,或以其他方式意外破坏事件。)

相比之下,a是使用值"string"初始化的7字节数据的第一个字节的常量地址。我没有为地址显示任何存储空间,因为与指针变量不同,没有一个可更改的存储空间来保存地址。您无法更改a指向的内存地址;它总是指向同一个空间。但您可以更改数组的内容(例如,strcpy(a, "select");)。

调用函数时,差异消失:

if (strcmp(ptr, a) == 0)
    …string is equal to string…

strcmp()函数接受两个指向常量字符数据的指针(因此它不会修改给予仔细检查的内容),并且ptra都被传递为指针值。有一种强有力的理由说只有指针传递给函数 - 从不传递数组 - 即使函数是使用数组符号编写的。

然而,这是至关重要的,数组(在参数列表之外)不是指针。断言的其他原因包括:

  • sizeof(a) == 7
  • sizeof(ptr) == 8(对于64位)或sizeof(ptr) == 4(32位)。

答案 1 :(得分:2)

  

如果是字符指针,它会存储哪个地址?这个块代表什么(我指向字符串的块)。它是"字符串"的起始地址。

此块表示WORD或DWORD(依赖于体系结构),此块的内容是内存地址,是在编译时定义的随机位置。该内存地址是字符串第一个字符的地址。

实际上,不同之处在于它使用了多少堆栈内存。

例如,当为微控制器编程时,为堆栈分配的内存非常少,会产生很大的不同。

char a[] = "string"; // the compiler puts {'s','t','r','i','n','g', 0} onto STACK 

char *b = "string"; // the compiler puts just the pointer onto STACK 
                    // and {'s','t','r','i','n','g',0} in static memory area.

也许这会帮助你理解。

assert(a[0] == 's'); // no error.
assert(b[0] == 's'); // no error.
assert(*b == 's');   // no error.
b++; // increment the memory address, so points to 't'
assert(*b == 's');   // assertion failed
assert(*b == 't');   // no error.

答案 2 :(得分:2)

char a[] = "string";使用值char初始化名为a的{​​{1}}数组的值。以及string的大小。

a在内存中的某处创建一个未命名的char *a = "string";静态数组,并将此未命名数组的第一个元素的地址返回给char

在第一个中,a存储数组的第一个元素的地址。因此,当我们索引像[4]这样的东西时,这意味着“采取”#39;名为a。

的对象开始后的第4个元素

在第二部分中,a表示“采取”#39;指向对象后面的第4个元素。

关于你的上一个问题:

char数组是一个'块' char类型的连续元素char指针是对char类型元素的引用。

由于指针算术,指针可用于模拟(和访问)数组。

也许这3个链接有助于更清楚地区分:

http://c-faq.com/decl/strlitinit.html

http://c-faq.com/aryptr/aryptr2.html

http://c-faq.com/aryptr/aryptrequiv.html

答案 3 :(得分:1)

您可能会发现有用的想法:

char * a = "string";

与:

相同
char SomeHiddenNameYouWillNeverKnowOrSee[] = "string";   /*  may be in ReadOnly memory! */
char * a = &SomeHiddenNameYouWillNeverKnowOrSee[0];

答案 4 :(得分:1)

你有没有试过用文本编辑器打开一些可执行文件?它看起来只是垃圾,但在垃圾的中间你可以看到一些可读的字符串。这些都是您程序中定义的所有字符串。

printf("my literal text");
char * c = "another literal text"; // should be const char *, see below

如果您的程序包含上述代码,您可以在程序的二进制文件中找到my literal textanother literal text(实际上它取决于二进制格式的详细信息,但它通常有效)。如果您是Linux / Unix用户,也可以使用strings命令。

顺便说一句,如果你编写上面的代码,C ++编译器会发出一些警告(g ++说:warning: deprecated conversion from string constant to ‘char*’因为这些字符串不是char *类型而是const char [](const char数组)当分配给指针时衰减到const char *

C编译器也是这种情况,但上述错误非常常见,通常会禁用此警告。 gcc甚至不包含在-Wall中,你必须通过-Wwrite-strings明确地启用它。警告为warning: initialization discards ‘const’ qualifier from pointer target type

它只是提醒你理论上不允许你通过指针改变文字文本。

可执行文件可以在数据段内存的只读部分加载此类字符串。如果您尝试更改字符串的内容,则可能会引发内存错误。此外,允许编译器通过合并相同的字符串来优化文本文本存储。指针只包含(只读)内存中将加载文字字符串的地址。

另一方面

char c[] = "string";仅仅是char c[7] = {'s', 't', 'r', 'i', 'n', 'g', 0};的语法糖如果在代码中执行sizeof(c),它将是7个字节(数组的大小,而不是指针的大小)。这是一个带有初始化器的堆栈数组。在内部,编译器可以执行它喜欢初始化数组。它可以是在数组中逐个加载的字符常量,也可以包含一些hiden字符串文字的memcpy。问题是你没有办法区分你的程序并找出数据的来源。只有结果很重要。

顺便说一下,有点令人困惑的是,如果你定义类型char c[]的某个函数参数,那么它将不是数组而是char * c的替代语法。

答案 5 :(得分:0)

在您的示例中,ptr包含字符串中第一个char的地址。

至于char数组和字符串之间的区别,在C术语中除了按照惯例我们称之为“string”的事实是最终char为NULL的char数组之外没有区别,以终止字符串。

即。即使我们有一个包含256个潜在元素的char数组,如果第一个(第0个)char为null(0),则字符串的长度为0.

考虑一个变量 str ,它是一个char 数组,包含5个字符,包含字符串'foo'

*ptr  =>   str[0]   'f'
           str[1]   'o'
           str[2]   'o'
           str[3]   \0
           str[4]   ..

此数组的 char * ptr 将引用第一个元素(index = 0),第4个元素(index = 3)将为null,标记'string'的结尾。第5个元素(index = 4)将被符合null终止符的字符串处理例程忽略。

答案 6 :(得分:-1)

如果您在询问每种情况下包含的内容,那么:

char a[] = "string";
// a is a pointer. 
// It contains the address of the first element of the array.

char *a = "string";
// Once again a is a pointer containing address of first element.

正如rnrneverdies在他的回答中所解释的那样,区别在于元素的存储位置。