use*_*750 30 c string pointers sizeof
#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;
}
Run Code Online (Sandbox Code Playgroud)
输出:
sizeof(str2): 10 bytes
sizeof(&str2): 4 bytes
Run Code Online (Sandbox Code Playgroud)
我知道str2
单独是数组中第一个元素的地址str2
.并且当str2
它的参数何时sizeof
返回整个数组str2的大小.
另外,&str2
也是arr中第一个元素的地址,str2
但是来自不同的类型(char (*)[N]
==指向数组的指针).但是&str2
当它是一个论证时,它是如何表现的sizeof
?
Gri*_*han 109
&str
和之间的区别str
,什么时候str
被宣布为char str[10]
?读 sizeof
操作员:
6.5.3.4 sizeof运算符,1125:
将sizeof
运算符应用于数组类型时,结果是数组中的总字节数.
因此,根据您的声明,sizeof(str2)
给出10个字节的完整数组大小(因为N定义为10,char大小为1个字节).
而在表达式中sizeof(&str2)
,&str2
是数组的地址和系统中4字节的地址大小.(地址大小在某些系统中可能为8字节,例如64位).
另外,
&str2
也是arr中第一个元素的地址str2
?
没有,价值观明智两个 &str2
和str
相同,但在语义上都是不同的.一个是10个字符数组的地址,而另一个是字符的地址.
你在自己的例子中看到的一个区别是它们是如何区别的(并且在这个答案中解释了@ouah).
str
是char[10]
&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
Run Code Online (Sandbox Code Playgroud)
对于上图,您可以编写代码:
#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));
}
Run Code Online (Sandbox Code Playgroud)
输出:
0xbf67e142, 0xbf67e143
0xbf67e142, 0xbf67e14c
Run Code Online (Sandbox Code Playgroud)
请注意,第一行输出地址差异是一个字节,但在第二行中差异是10个字节,因为它的数组的指针(如上图所示).
根据指针数学规则,当你向指针变量添加1时,它开始指向它自己类型的下一个元素,这是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));
}
Run Code Online (Sandbox Code Playgroud)
输出:
0xbf587046 H, 0xbf587046 H
Run Code Online (Sandbox Code Playgroud)
在输出中
str2 gives 0xbf587046
*(str2) H
*(&str2) 0xbf587046
**(&str2) H
Run Code Online (Sandbox Code Playgroud)
这意味着*(&str2) == str2
价值就是地址.因此*(str2) = **(&str2)
价值观是H
.
编辑: 上面我显示了区别&str
和str
哪里str
是类型的数组char[10]
.
char *str
以及char str[]
两者如何存储在内存中假设我们有两个声明,如下所示:
char *str1 = "hello";
char str2[] = "hello";
Run Code Online (Sandbox Code Playgroud)
在上面的声明str1
是一个指向char
,即指向一个常数字符串文字(由保持第一个字符的地址h
在"hello"
字符串).
C中的字符串是char[N]
(数组)类型,这就是为什么sizeof("hello")
给出6因为"hello"
字符串是6个字符长数组(包括\0
nul,字符串终止,hello的类型是char[6]
).
在内存中,您的"hello"
字符串存储如下:
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
Run Code Online (Sandbox Code Playgroud)
char* str1 = "hello";
基本上将字符串hello的地址存储到指针变量str1
,如上图所示.
注意:如果您最近想要代码,则将更改更改str1
为指向其他字符串.但你无法修改hello
字符串.例如以下代码有效:
char* str1 = "hello"; // str1 points to hello str1-->"hello"
str1 = "world"; //Now, str1 points to world str1-->"world"
Run Code Online (Sandbox Code Playgroud)
现在str1
指向其他常量字符串世界.
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.
Run Code Online (Sandbox Code Playgroud)
需要注意的重要事项:str1
指向常量字符串,因此您无法通过访问/索引内存位置来修改字符串,例如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;
}
Run Code Online (Sandbox Code Playgroud)
输出:
str1: Hello, address: 0x80485e8, sizeof(str1): 4
str1: world, address: 0x8048619, sizeof(str1): 4
Run Code Online (Sandbox Code Playgroud)
因此,要分配新字符串,我只需指定新字符串的地址.但是我不能打电话strcpy()
,会尝试在只读内存位置写入,这是非法的.
在第二个声明中char str2[] = "hello";
,str2[]
是一个\0
终止的字符数组(或字符串),但不是指针.注意因为在这个声明中大小没有给出默认大小,我们那个常量字符串"hello"的大小就是6.类型str2
是char[6]
.
当我们char str2[] = "hello";
创建一个char数组并将hello字符串复制到该数组中时,str2
不仅仅是指针而是存储完整字符串的数组.
它的概念在于.
str2:
103 104 105 106 107 108
+----+----+----+----+----+----+
| h | e | l | l | o | \0 |
+----+----+----+----+----+----+
Run Code Online (Sandbox Code Playgroud)
而在这种情况下,最近在你的代码你不会允许这样做str2[] = "world";
或str2 = "world"
感染这将是编译时错误.
示例代码:
#include<stdio.h>
int main(){
char str2[] = "hello";
str2[] = "world";
str2 = "world";
return 1;
}
Run Code Online (Sandbox Code Playgroud)
编译错误:
In function 'main':
Line 4: error: expected expression before ']' token
Line 5: error: incompatible types in assignment
Run Code Online (Sandbox Code Playgroud)
如果这个数组str2
不是常数,我们可以修改它的内容,例如do 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.
Run Code Online (Sandbox Code Playgroud)
代码示例:
#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;
}
Run Code Online (Sandbox Code Playgroud)
输出:
str2: hello, address: 0xbf58d056, sizeof(str2): 6
str2: heAlo, address: 0xbf58d056, sizeof(str2): 6
str2: world, address: 0xbf58d056, sizeof(str2): 6
Run Code Online (Sandbox Code Playgroud)
注意:字符串值在同一地址空间中是不同的.sizeof(str2)
从旧答案中完全理解= 6,即以字节为单位的数组大小.
读取类似的描述约2维阵列读取:差异char* str[]
和char str[][]
在存储器中,以及如何都店?
str2
是类型char [10]
(即数组10 of
char`)
&str2
是类型char (*)[10]
(即指向数组10
的指针char
).
因此sizeof (&str2)
产生指针类型的对象的大小char (*)[10]