2017-09-28 104 views
2

所以我試圖扭轉一個字符串,但我得到一個內存故障。 s和s1的存儲器初始化足以容納'/ 0'字符。內存故障和指向字符串的指針

有趣的是,如果我刪除* s = * s1並打印s1而不是程序工作。 但是我甚至沒有在s1的末尾設置「\ 0」字符,所以它甚至不知道在哪裏停止打印?

而在下面的情況下究竟是什麼問題?

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 

void main(void) 
{ 
    char *s = "abcdefghijklmnop", *s1=malloc(17); 
    int i; 
    for(i=0;i<strlen(s);i++) 
    { 
     *(s1+i) = *(s+strlen(s)-1-i); 
    } 
    *s=*s1; 
    printf("%s",s); 
} 
+1

你認爲'* s = * s1'和's = s1'之間的區別是什麼? –

+0

前者取值s1指向並將其放在地址s中指向,而後者指向s1指向 – CodeChef123

+0

@ScottHunter:好的,我明白了爲什麼應該起作用。但是* s1 * s1 – CodeChef123

回答

3

char *s = "abcdefghijklmnop"是一個字符串文字,它通常在只讀存儲器中。 如果您嘗試修改字符串文字,則會生成錯誤。

當您執行*s=*s+1時,您試圖將s中的第一個字符替換爲s1中的第一個字符。

如果s不是字符串文字,則應該執行s=s1而不是*s=*s1,以使s反轉。

更多關於這一點:

https://softwareengineering.stackexchange.com/questions/294748/why-are-c-string-literals-read-only
String literals: Where do they go?
where in memory are string literals ? stack/heap?

正確的串印有printf("%s", s1);即使沒有\0儲存,因爲內存旁邊正好是0的最後一個字符,其相當於\0。這並不總是如此,並且不能被依賴,因爲malloc()不初始化它分配的內存。

calloc()初始化它分配給0的內存。

查看更多here

+0

好的,所以實際上* s = * s1只會替換第一個字符?不是整個字符串? – CodeChef123

+0

@ CodeChef123沒錯。如果's'不是一個字符串文字並且可以修改,你應該已經完成​​了's = s1'。並且不要忘記用'free(s1)''釋放's1'的內存。 –

+0

所以你說地址是指向在ROM?是否有任何理由,因爲它似乎更像一個正常的指針(* ints,例如) – CodeChef123

0

在您的代碼*s=*s1中,只將s1的第一個內容複製到s中。即*(s+0)=*(s1+0)不是整個字符串。所以我們需要將s1的地址分配給s。即,s=s1

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h>  

int main() 
{ 
    char *s = "abcdefghijklmnop", *s1=malloc(17); 
    int i; 
    for(i=0;i<strlen(s);i++) 
    { 
     *(s1+i) = *(s+strlen(s)-1-i); 
    } 
    s=s1; 
    printf("%s",s); 
    free(s1); 
    return 0; 
} 

在使用後釋放內存是一種很好的做法。