C 为什么sizeof(msg)比字符串短?
我刚刚开始学习如何编程,我正在使用这本书叫做Head First C。书中有一些章节叫做脑力。在其中一个章节中,它被写了下来C 为什么sizeof(msg)比字符串短?,c,pointers,C,Pointers,我刚刚开始学习如何编程,我正在使用这本书叫做Head First C。书中有一些章节叫做脑力。在其中一个章节中,它被写了下来 void fortune_cookie(char msg[]) { printf("Message reads: %s\n", msg); printf("msg occupies %i bytes\n", sizeof(msg)); } 输出: 饼干使你发胖 msg占用8个字节 脑力问题是:为什么你认为sizeof(ms
void fortune_cookie(char msg[])
{
printf("Message reads: %s\n", msg);
printf("msg occupies %i bytes\n", sizeof(msg));
}
输出:
饼干使你发胖
msg占用8个字节
脑力问题是:为什么你认为
sizeof(msg)
比整个字符串的长度短?什么是msg
?为什么它会在不同的机器上返回不同的大小?在这种特殊情况下
char msg[]
与
char * msg
因此,您真正看到的是sizeof(char*)
的输出
由于指针的大小取决于体系结构/编译器,您将在不同的机器中看到不同的输出
另外,请注意,由于
sizeof
运算符生成类型为size\t
的结果,您应该使用%zu
格式说明符打印结果。为什么您认为sizeof(msg)比整个字符串的长度短?
因为数组
在作为参数传递给某个函数时会衰减为指针
int arr[10];
printf("%zu", sizeof(arr));
这将返回40
。考虑到int
的大小是4
但当发送到函数时
void func(int arr[])
{
printf("%lu", sizeof(arr));
}
这将返回sizeof(int*)
什么是味精?
msg
是发送到函数的char
数组
int arr[10];
printf("%zu", sizeof(arr));
为什么它会在不同的机器上返回不同的大小?
因为内存地址的大小对于不同的机器架构是不同的,因此使得
sizeof(int*)
不同。下面的代码应该可以回答您的问题:
#include <stdio.h>
#include <string.h>
void foo(char *msg){
printf("\n");
printf("Sizeof MSG = %zu\n", sizeof(msg));
printf("Length of MSG = %zu\n", strlen(msg));
}
int main(void) {
char msg[10] = "Michi";
printf("Sizeof MSG = %zu\n", sizeof(msg));
printf("Length of MSG = %zu\n", strlen(msg));
foo(msg);
return 0;
}
为什么Sizeof MSG=10
在main
中?因为要打印数组的大小
为什么Sizeof MSG=8
在foo
中?因为您打印的是指针的大小,而在您的机器上(像我的一样)恰好是8
当数组用作函数参数时,数组衰减为指向其第一个元素的指针
换句话说,像这样的事情:
#include <stdio.h>
#include <string.h>
void foo(int *msg){
printf("\n");
printf("Sizeof MSG = %zu\n", sizeof(msg));
printf("Length of MSG = %zu\n", strlen(msg));
}
int main(void) {
int msg[10] = {1,2,3,4,5};
printf("Sizeof MSG = %zu\n", sizeof(msg));
printf("Length of MSG = %zu\n", strlen(msg));
foo(msg);
return 0;
}
size_t strlen(const char *str)
#include <stdio.h>
#include <string.h>
void foo(int *msg, size_t length){
size_t i=0;
printf("\n\n");
printf("Sizeof MSG = %zu\n",length);
for (i = 0; i<length;i++){
printf("%d ",msg[i]);
}
}
int main(void) {
int msg[] = {1,2,3,4,5,6,7,8,9,10};
size_t length = sizeof msg / sizeof msg[0];
size_t i=0;
printf("\n");
printf("Sizeof MSG = %zu\n",length);
for (i = 0; i<length;i++){
printf("%d ",msg[i]);
}
foo(msg, length);
return 0;
}
因为strlen的定义如下:
#include <stdio.h>
#include <string.h>
void foo(int *msg){
printf("\n");
printf("Sizeof MSG = %zu\n", sizeof(msg));
printf("Length of MSG = %zu\n", strlen(msg));
}
int main(void) {
int msg[10] = {1,2,3,4,5};
printf("Sizeof MSG = %zu\n", sizeof(msg));
printf("Length of MSG = %zu\n", strlen(msg));
foo(msg);
return 0;
}
size_t strlen(const char *str)
#include <stdio.h>
#include <string.h>
void foo(int *msg, size_t length){
size_t i=0;
printf("\n\n");
printf("Sizeof MSG = %zu\n",length);
for (i = 0; i<length;i++){
printf("%d ",msg[i]);
}
}
int main(void) {
int msg[] = {1,2,3,4,5,6,7,8,9,10};
size_t length = sizeof msg / sizeof msg[0];
size_t i=0;
printf("\n");
printf("Sizeof MSG = %zu\n",length);
for (i = 0; i<length;i++){
printf("%d ",msg[i]);
}
foo(msg, length);
return 0;
}
如您所见,strlen需要char*
而不是int*
要修复它,还需要传递长度,如下所示:
#include <stdio.h>
#include <string.h>
void foo(int *msg){
printf("\n");
printf("Sizeof MSG = %zu\n", sizeof(msg));
printf("Length of MSG = %zu\n", strlen(msg));
}
int main(void) {
int msg[10] = {1,2,3,4,5};
printf("Sizeof MSG = %zu\n", sizeof(msg));
printf("Length of MSG = %zu\n", strlen(msg));
foo(msg);
return 0;
}
size_t strlen(const char *str)
#include <stdio.h>
#include <string.h>
void foo(int *msg, size_t length){
size_t i=0;
printf("\n\n");
printf("Sizeof MSG = %zu\n",length);
for (i = 0; i<length;i++){
printf("%d ",msg[i]);
}
}
int main(void) {
int msg[] = {1,2,3,4,5,6,7,8,9,10};
size_t length = sizeof msg / sizeof msg[0];
size_t i=0;
printf("\n");
printf("Sizeof MSG = %zu\n",length);
for (i = 0; i<length;i++){
printf("%d ",msg[i]);
}
foo(msg, length);
return 0;
}
在C语言中,字符串和数组不是一级数据类型,因此不能通过副本传递。尽管支持参数类型语法
char msh[]
,但其语义与char*msg
相同。数组参数语法的作用仅仅是向开发人员指示函数希望msg
引用数组,而不是指向单个项的指针
如果msg
是以nul结尾的字符串,或者是具有sentinel值的数组,则可能不需要传递数组长度,但在许多情况下这样做很有用
您可以使用的一个技巧是将数组包装在结构中,该结构是第一类类型,可以通过副本或指针传递。出于性能方面的考虑,通过指针传递通常更可取,但无论如何,成员的大小都是已知的
typedef struct { char data[32] ; } sMsgContainer ;
void fortune_cookie( const sMsgContainer msg )
{
printf( "Message reads: %s\n", msg.data ) ;
printf( "msg occupies %i bytes\n", sizeof(msg) ) ;
printf( "msg.data occupies %i bytes\n", sizeof(msg.data) ) ;
}
void fortune_cookie2( sMsgContainer* msgp )
{
printf( "Message reads: %s\n", msgp.data ) ;
printf( "msgp occupies %i bytes\n", sizeof(msgp) ) ;
printf( "msgp->data occupies %i bytes\n", sizeof(msg->data) ) ;
}
然后给出:
sMsgContainer msg = {"Cookies make you happy"} ;
fortune_cookie( msg ) ;
fortune_cookie2( &msg ) ;
输出
Message reads: Cookies make you happy
msg occupies 32 bytes
msg.data occupies 32 bytes
Message reads: Cookies make you happy
msgp occupies 4 bytes
msgp->data occupies 32 bytes
出于对齐目的,msg
的长度可能大于msg.data
,但这是实现定义的。您的意思是片段的可能重复
不是和平