C 为什么sizeof(msg)比字符串短?

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

我刚刚开始学习如何编程,我正在使用这本书叫做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(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
,但这是实现定义的。

您的意思是
片段的可能重复
不是
和平