[英]String vs String Literal: Direct assignment or strcpy/strncpy?
[英]strncpy vs direct assignment seg fault
以下代碼在沒有段錯誤的情況下運行
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node {
char *data;
struct node *next;
};
int main(void)
{
struct node *head = malloc(sizeof(struct node));
head->data = "test";
printf("data: %s\n", head->data);
return 0;
}
當我將代碼切換為
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node {
char *data;
struct node *next;
};
int main(void)
{
struct node *head = malloc(sizeof(struct node));
strncpy(head->data, "test", 512);
printf("data: %s\n", head->data);
return 0;
}
我收到段錯誤並被迫將我的節點屬性數據切換為 char 數據 [512] 類型。 為什么這是必需的? 我認為 arrays 本質上是指針,所以這種行為對我來說沒有意義。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node {
char data[512];
struct node *next;
};
int main(void)
{
struct node *head = malloc(sizeof(struct node));
strncpy(head->data, "test", 512);
printf("data: %s\n", head->data);
return 0;
}
我希望指針和 arrays 都可以以相同的方式分配字符串值。
在這份聲明中
head->data = "test";
具有數組類型char[5]
的字符串文字被隱式轉換為指向其第一個元素的指針,並且該指針被分配給指針head->data
。
在這份聲明中
strncpy(head->data, "test", 512);
您正在使用未初始化的指針head->data
並嘗試將整個字符串文字復制到該指針指向的具有不確定值的 memory 。 這會調用未定義的行為。
我認為 arrays 本質上是指針,所以這種行為對我來說沒有意義。
Arrays 不是指針。 在大多數情況下,它們可以隱式轉換為指向其第一個元素的指針,但這並不意味着 arrays 是指針。
考慮下面的簡單演示程序。
#include <stdio.h>
int main( void )
{
char data[512];
char *p = data;
printf( "sizeof( data ) = %zu\n", sizeof( data ) );
printf( "sizeof( p ) = %zu\n", sizeof( p ) );
}
它的 output 可能看起來像
sizeof( data ) = 512
sizeof( p ) = 8
在第二個片段(崩潰的片段)中,您為node
結構分配了 memory,其中包括指針data
。 然而,這個指針永遠不會被初始化,它指向某個任意的 memory 地址(或者只是NULL
),這意味着寫入它是未定義的行為,而且確實可能只是段錯誤。
要使其指向有效的 memory 地址,您必須顯式分配它:
struct node *head = malloc(sizeof(struct node));
head->data = malloc(sizeof(char) * 512 /* or some other size, of course */);
為什么這是必需的? 我認為 arrays 本質上是指針,所以這種行為對我來說沒有意義。
指針只是指針,它們占用的唯一 memory 是存儲地址所需的 memory。 如果你想要一個指針指向動態分配的memory,你需要自己分配它。
例子:
struct node {
char *data;
struct node *next;
};
struct node *create_node(const char *str) {
struct node *nn = malloc(sizeof *nn);
if(nn) {
nn->data = strdup(str); // allocate strlen(str)+1 bytes and copy the string
if(nn->data) { // strdup was successful
nn->next = NULL;
} else { // strdup failed
free(nn);
nn = NULL;
}
}
return nn;
}
void destroy_node(struct node *n) {
free(n->data);
free(n);
}
我認為 arrays 本質上是指針
數組與指針:
數組可能會衰減為表達式中的指針和 function 參數,並且數組訪問可能會被編譯器重寫為指針訪問,但它們不可互換。 數組名是地址,指針是地址的地址。
為什么這是必需的?
聲明一個指針只會為指針分配 memory。
您可以通過兩種方式初始化指針:
使用字符串文字:
ptr = "abcd";
最初, ptr
是不確定的。 但這改變了它指向的內容,現在它指向一個字符串文字。 編譯器會將字符串文字的第一個元素的地址存儲在ptr
中。
如果你對一個做同樣的事情
大批:
char s[] = "String";
然后嘗試更改其值:
s = "String2"; /* error: assignment to expression with array type */
它不會編譯,因為 arrays 與指針不同,它不是可修改的左值。 你不能改變它的價值。
或者給它分配memory然后
寫信給它。
errno = 0; ptr = malloc (size); if (;ptr) { errno = ENOMEM; perror ("malloc ()"). deal with error here... }
現在你可以使用strcpy ()
來復制它了。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.