sizeof(&array)返回什么?
下面的问题: 一个数组的地址是如何等于它在C中的值?
#include <stdio.h> #define N 10 char str2[N]={"Hello"}; int main(){ printf("sizeof(str2): %d bytes\n", sizeof(str2)); printf("sizeof(&str2): %d bytes\n", sizeof(&str2)); return 0; }
输出:
sizeof(str2): 10 bytes sizeof(&str2): 4 bytes
我知道str2
本身就是str2
中第一个元素的地址。 而当str2
是sizeof
的参数时,它将返回整个数组str2的大小。
另外, &str2
也是arr str2
第一个元素的地址,但是来自于不同types( char (*)[N]
==指向数组的指针)。 但是当&str2
是一个sizeof
的参数时, &str2
如何performance的?
&str2
是一个指针。 所以你只是看到你的平台上的指针的大小。
当str
被声明为char str[10]
时, &str
和str
之间的区别?
阅读sizeof
运营商:
6.5.3.4运营商的规模,1125:
将sizeof
运算符应用于数组types时,结果是数组中的总字节数。
因此,根据您的声明, sizeof(str2)
给出了10个字节的完整数组大小(因为N定义为10,char大小为1个字节)。
而在expression式sizeof(&str2)
, &str2
是您的系统中4个字节的地址数组和地址的大小。 (在一些系统中,地址大小可能是8字节,例如64位)。
另外,
&str2
也是arrstr2
第一个元素的地址?
不 ,value-wise &str2
和str
都是相同的,但是在语义上都是不同的 。 一个是10个字符的数组的地址,而另一个是char的地址。
你在自己的例子中看到的一个区别是它们是如何不同的(在这个答案中解释了@ouah)。
-
str
types是char[10]
- types的
&str
是char(*)[10]
第二:下图将帮助您观察其他差异。
for declaration: #define N 10 char str2[N] = {"Hello"}; str2 Array in memory is something like: ---------------------------------------- str +----+----+----+----+----+----+----+----+----+----++----+ |'H' |'e' |'l' |'l' |'o' |'\0'|'\0'|'\0'|'\0'|'\0'|| '@'| +----+----+----+----+----+----+----+----+----+----++----+ 201 202 203 204 205 206 207 208 209 210 211 ▲ ▲ ▲ ▲ | | | | |(str2) (str2 + 1) | | | |-----------------------------------------------------| |201 | | | | | (&str2) = 201 (&str2 + 1) = 211 * assuming str address start from 201 * str[N] is 10 char long 201-210, partially initialized * at uninitialized position, str2[i] = '\0' * location 211 is unallocated, having garbage value, access to this location is illegal-Undefined Behavior
对于上面的图你可以写一个代码:
#include <stdio.h> #define N 10 int main(){ char str2[N]={"Hello"}; printf("\n %p, %p\n",str2, str2+1); printf("\n %p, %p\n",(&str2), (&str2+1)); }
输出:
0xbf67e142, 0xbf67e143 0xbf67e142, 0xbf67e14c
键盘的链接:
注意第一行输出地址差异是一个字节,但是第二行差异是10字节,因为它的数组指针(如上图所示)。
根据指针math规则,当你给指针variables加1时,它开始指向它自己types的下一个元素,这就是10字节差异的原因,因为&str2
是数组地址。
第三个区别:
通过做*str2
你可以访问第一个元素。 *(&str2)
不会给你第一个元素,而是第一个元素的地址。
一个例子将在这里帮助:
#include <stdio.h> #define N 10 int main(){ char str2[N]={"Hello"}; printf("\n%p %c, %p %c\n",str2, *(str2), *(&str2), **(&str2)); }
输出:
0xbf587046 H, 0xbf587046 H
键盘链接
在输出
str2 gives 0xbf587046 *(str2) H *(&str2) 0xbf587046 **(&str2) H
这意味着*(&str2) == str2
和值是地址。 因此*(str2) = **(&str2)
值是H
编辑:上面我显示了&str
和str
之间的区别,其中str
是char[10]
types的数组。
char *str
和char str[]
之间的区别以及两者如何存储在内存中
假设我们有两个声明如下:
char *str1 = "hello"; char str2[] = "hello";
在上面的声明中, str1
是一个指向char
的指针,指向一个常量string(通过在"hello"
string中保存第一个char h
地址)。
C中的一个string是char[N]
(array)types,这就是为什么sizeof("hello")
给出6的原因,因为"hello"
string是6个字符长数组(包括\0
nul,string终止,hellotypes是char[6]
)。
在内存中, "hello"
string的存储方式如下所示:
str1 23 24 25 26 27 28 +----+ +----+----+----+----+----+----+ | 23 | | h | e | l | l | o | \0 | +----+ +----+----+----+----+----+----+ +-----------▲ here address of hello string is first address = 23. str1: is pointer capable to store address. "hello" consists of 6 chars
char* str1 = "hello";
基本上将stringhello的地址存储到指针variablesstr1
,如上图所示。
注意:如果你最近想在你的代码中改变str1
来指向另一个string。 但是你不能修改hello
string。 例如下面的代码是有效的:
char* str1 = "hello"; // str1 points to hello str1-->"hello" str1 = "world"; //Now, str1 points to world str1-->"world"
现在str1
指向其他常量string的世界。
str1 93 94 95 96 97 98 +----+ +----+----+----+----+----+----+ | 93 | | w | o | r | l | d | \0 | +----+ +----+----+----+----+----+----+ +-----------▲ here address of world string is first address = 93. str1: value change to point string world.
重要的是要注意: str1
指向常量string,因此您不能通过访问/索引内存位置来修改string,例如str1[i] = 'A'
; 将是非法的,因为你正在写只读内存 ,这是行为未定义在运行时(虽然没有编译错误,因为在语法上是正确的)。
再次,因为str1
是一个指针sizeof(str1)
将在同一台机器上给4。
我的下面的代码和它的运行:
#include <stdio.h> int main(){ char* str1="Hello"; printf("\nstr1: %s, address: %p, sizeof(str1): %u", str1, str1, sizeof(str1)); str1 = "world"; printf("\nstr1: %s, address: %p, sizeof(str1): %u", str1, str1, sizeof(str1)); return 1; }
输出:
str1: Hello, address: 0x80485e8, sizeof(str1): 4 str1: world, address: 0x8048619, sizeof(str1): 4
键盘链接
所以,分配新的string我只是分配新的string的地址。 但是我不能调用strcpy()
,它会尝试写入只读内存位置,这是非法的。
在第二个声明char str2[] = "hello";
, str2[]
是字符(或string)的终止数组,但是不是指针。 注意,因为在这个声明中没有给出大小的默认大小,我们将那个常量string“hello”的大小定义为6. str2
types是char[6]
。
当我们做char str2[] = "hello";
一个char数组创build和hellostring将被复制到该数组所以str2
不是简单的指针,而是一个数组存储完整的string。
它在概念上就像。
str2: 103 104 105 106 107 108 +----+----+----+----+----+----+ | h | e | l | l | o | \0 | +----+----+----+----+----+----+
在这种情况下,最近在你的代码中,你不允许做str2[] = "world";
或str2 = "world"
感染它将是编译时间错误。
示例代码:
#include<stdio.h> int main(){ char str2[] = "hello"; str2[] = "world"; str2 = "world"; return 1; }
编译错误:
In function 'main': Line 4: error: expected expression before ']' token Line 5: error: incompatible types in assignment
代码链接
在这个数组str2
不是常量的地方,我们可以修改它的内容,比如str2[2] = 'A'
是完全有效的。 我们也可以调用strcpy来改变内容(并且地址空间不会改变)
strcpy(str2, "world"); str2: 103 104 105 106 107 108 +----+----+----+----+----+----+ | w | o | r | l | d | \0 | +----+----+----+----+----+----+ Note world coped into same memory space, address of world and hello string is name.
代码示例:
#include<stdio.h> int main(){ char str2[] = "hello"; printf("\nstr2: %s, address: %p, sizeof(str2): %u", str2, str2, sizeof(str2)); str2[2] = 'A'; printf("\nstr2: %s, address: %p, sizeof(str2): %u", str2, str2, sizeof(str2)); strcpy(str2, "world"); printf("\nstr2: %s, address: %p, sizeof(str2): %u", str2, str2, sizeof(str2)); return 1; }
输出:
str2: hello, address: 0xbf58d056, sizeof(str2): 6 str2: heAlo, address: 0xbf58d056, sizeof(str2): 6 str2: world, address: 0xbf58d056, sizeof(str2): 6
键盘链接
注意:string值在相同的地址空间上是不同的。 sizeof(str2)
= 6完全可以从旧的答案中理解,即字节数组的大小。
阅读有关2维数组读取类似的描述: char* str[]
和char str[][]
之间的区别,以及如何在内存中存储?
str2
的types是char [10]
(即char [10]
数组10 of
)
&str2
的types是char (*)[10]
(即指向char
数组10
的指针)。
所以sizeof (&str2)
产生一个指针typeschar (*)[10]
的对象的大小char (*)[10]