c程序没有给我错误
c program doesn't give me errors
考虑以下程序
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct my_string{
int len;
char *buf;
} my_string_t;
my_string_t *init_my_string(char *);
my_string_t *call_init_my_string();
int main(int argc, char *argv[])
{
my_string_t *st1 = call_init_my_string();
printf("%d\n", st1->len);
printf("%s\n", st1->buf);
free(st1);
return 0;
}
my_string_t *call_init_my_string()
{
my_string_t *st1 = init_my_string("Foo");
return st1;
}
my_string_t *init_my_string(char *s)
{
my_string_t *st = (my_string_t *) malloc(sizeof(*st));
st->len = strlen(s);
st->buf = s;
return st;
}
问题是,
该程序是否会导致未定义的行为或某种错误?
因为函数 call_init_my_string
中的字符串 "Foo"
是在本地声明的
并传递给 init_my_string
函数。在 init_my_string
函数中,我分配
a space 来保存字符串的大小和字符串本身,但据我所知,这
分配
my_string_t *st = (my_string_t *) malloc(sizeof(*st));
只分配足够 space 给 st->len
和 st->buf
指针而不是字符串 "Foo"
因为我只分配字符串
到 st->buf
而不是先分配它然后像下面这样:
st->buf = (char *) malloc(strlen(s) + 1);
memcpy(st->buf, s, strlen(s));
st->buf[strlen(s)] ='[=11=]';
但是在我编译它并 运行 之后,它没有给我任何错误并且程序 运行 没问题。
为什么这个程序工作正常并且没有给我任何错误?
这是屏幕上打印的结果:
$ gcc struct_ptr_string1.c -o struct_ptr_string1
$ ./struct_ptr_string1
3
Foo
"Foo" 字符串是一个可能静态存储在某处的常量字符串。 init_my_string
中发生的事情是您确实分配了一个新的内存块,但是您会将 st->buf
分配给 s
,这是指向此 "Foo" 字符串的指针。所以你不复制 "Foo",而是将 st->buf
设置到它存储的位置。
my_string_t *init_my_string(char *s)
{
my_string_t *st = (my_string_t *) malloc(sizeof(*st));
printf("st address=%d\n", st);
printf("s address=%d\n", s);
st->len = strlen(s);
st->buf = s;
printf("st->buf address=%d\n", st->buf);
return st;
}
输出:
st address=19779600
s address=4196344
st->buf address=4196344
3
Foo
如您所见,st->buf
实际上指向常量字符串,这就是为什么没有错误。
您的代码中没有未定义的行为。
字符串文字 "Foo"
具有 静态存储持续时间 。您将其地址传递给 init_my_string
并简单地存储该地址(本质上是指向 "Foo"
的指针)。
您的代码等同于(除了我们还有一份 "Foo"
):
my_string_t *call_init_my_string()
{
static char s[] = "Foo";
my_string_t *st1 = init_my_string(&s[0]);
return st1;
}
my_string_t *init_my_string(char *s)
{
my_string_t *st = malloc(sizeof(*st));
st->len = strlen(s);
st->buf = s;
return st;
}
考虑以下程序
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct my_string{
int len;
char *buf;
} my_string_t;
my_string_t *init_my_string(char *);
my_string_t *call_init_my_string();
int main(int argc, char *argv[])
{
my_string_t *st1 = call_init_my_string();
printf("%d\n", st1->len);
printf("%s\n", st1->buf);
free(st1);
return 0;
}
my_string_t *call_init_my_string()
{
my_string_t *st1 = init_my_string("Foo");
return st1;
}
my_string_t *init_my_string(char *s)
{
my_string_t *st = (my_string_t *) malloc(sizeof(*st));
st->len = strlen(s);
st->buf = s;
return st;
}
问题是,
该程序是否会导致未定义的行为或某种错误?
因为函数 call_init_my_string
中的字符串 "Foo"
是在本地声明的
并传递给 init_my_string
函数。在 init_my_string
函数中,我分配
a space 来保存字符串的大小和字符串本身,但据我所知,这
分配
my_string_t *st = (my_string_t *) malloc(sizeof(*st));
只分配足够 space 给 st->len
和 st->buf
指针而不是字符串 "Foo"
因为我只分配字符串
到 st->buf
而不是先分配它然后像下面这样:
st->buf = (char *) malloc(strlen(s) + 1);
memcpy(st->buf, s, strlen(s));
st->buf[strlen(s)] ='[=11=]';
但是在我编译它并 运行 之后,它没有给我任何错误并且程序 运行 没问题。 为什么这个程序工作正常并且没有给我任何错误?
这是屏幕上打印的结果:
$ gcc struct_ptr_string1.c -o struct_ptr_string1
$ ./struct_ptr_string1
3
Foo
"Foo" 字符串是一个可能静态存储在某处的常量字符串。 init_my_string
中发生的事情是您确实分配了一个新的内存块,但是您会将 st->buf
分配给 s
,这是指向此 "Foo" 字符串的指针。所以你不复制 "Foo",而是将 st->buf
设置到它存储的位置。
my_string_t *init_my_string(char *s)
{
my_string_t *st = (my_string_t *) malloc(sizeof(*st));
printf("st address=%d\n", st);
printf("s address=%d\n", s);
st->len = strlen(s);
st->buf = s;
printf("st->buf address=%d\n", st->buf);
return st;
}
输出:
st address=19779600
s address=4196344
st->buf address=4196344
3
Foo
如您所见,st->buf
实际上指向常量字符串,这就是为什么没有错误。
您的代码中没有未定义的行为。
字符串文字 "Foo"
具有 静态存储持续时间 。您将其地址传递给 init_my_string
并简单地存储该地址(本质上是指向 "Foo"
的指针)。
您的代码等同于(除了我们还有一份 "Foo"
):
my_string_t *call_init_my_string()
{
static char s[] = "Foo";
my_string_t *st1 = init_my_string(&s[0]);
return st1;
}
my_string_t *init_my_string(char *s)
{
my_string_t *st = malloc(sizeof(*st));
st->len = strlen(s);
st->buf = s;
return st;
}