C語言char s[]和char* s的區(qū)別
C語言指針可以代替數(shù)組使用
1、數(shù)組本質
數(shù)組是多個元素的集合,在內存中分布在地址連續(xù)的單元中,因此可以通過其下標訪問數(shù)組的不同數(shù)組。
例如:
下面展示一些
char s[3] = "0x1"; printf("s2字符串:\n"); printf("%c\n", s[0]); printf("%c\n", s[1]); printf("%c\n", s[2]);
2、指針
指針也是一種變量,只不過它的內存單元中保存的是一種標識其他位置的地址,而地址也是整數(shù),在32位平臺下,就是32位,4個字節(jié)(bytes)。
指針的指向
指針的指向是指 指針變量所保存的其他的地址單元中 所存放的數(shù)據(jù)類型。
例如:
int *ptr;//ptr指針保存的地址所在內存單元中的數(shù)據(jù)類型是整型 float *p;//這個p指針指向的內存地址存放的元素類型就是浮點型
而不管指向的數(shù)據(jù)類型是哪種,其實對于指針本身的值永遠是整型,因為它保存的地址就是整數(shù)
3、字符數(shù)組
字符數(shù)組首先是數(shù)組,數(shù)組中的元素都是字符。
char s[10];//定義了一個含有10個元素的數(shù)組,元素類型為字符 %c
C語言中定義一個變量時,可以初始化,如下:
char s[10] = {"hello world"};
當編譯器遇到上面的定義和賦值時,會將 hello world 和 \0 依次逐個填入連續(xù)數(shù)組內存中。
C語言中是沒有真正的字符串類型,可以通過字符數(shù)組表示字符串,并且字符數(shù)組的元素地址也是連續(xù)的。C語言中規(guī)定數(shù)組代表數(shù)組所在內存位置的首地址,即 str字符串是等于str[0]的,str = &str[0];
對于printf("%s",str); 為什么用首地址就可以輸出字符串?
因為對于C語言中字符串常量的本質就是一個地址,例如:
char *s ; s = "Hello";
這里把一個字符串賦值給一個字符串指針變量,起始就是C語言中編譯器會給字符串常量分配地址,如果"Hello", 存儲在內存中的 0x3000 0x3001 0x3002 0x3003 0x3004 0x3005 ,可以看出真正的意義就是
s = “Hello” = 0x3000
因此我們可以把Hello看做是字符串,而編譯器會把他看做是地址 0x3000 ,即字符串常量的本質就是代表它的第一個字符的地址。
char *s; s = "Hello"; printf("%p\n",s);//%p代表表示按十六進制輸出數(shù)據(jù),如果輸出數(shù)據(jù)不夠8位數(shù),則左邊補0
輸出00796BD0,也就是"Hello"的首地址。
對于字符數(shù)組:
char str[10] = “Hello”;
也就是說str = &str[0]
C語言中操作字符串是通過它在內存中的存儲單元的首地址進行的,這是字符串的終極本質。。。
4、char * 與 char a[ ]
對于char *s 與 char a[ ] :
a代表的是字符串的首地址,而s代表的這個指針保存字符串的首地址(第一個字符的地址),即可以看做: s =a ,即可以將數(shù)組名賦值給指針表示地址,但是 不能這樣賦值 a = s ,即:不能將指針賦值給數(shù)組名
因為數(shù)組名是一個常量,是不可以修改的
可以通過如下方式訪問數(shù)組元素:
char a[] = "Hello"; char*s = a; int i; for(i = 0;i < strlen(a);i++) { printf("%c",s[i]); //printf("%c",*s++);也可以 }
字符指針可以用 間接操作符 * 取其內容,也可以用數(shù)組的下標形式 [ ],數(shù)組名也可以用 *操作,因為它本身表示一個地址 。。
比如 printf("%c",*a); 將會打印出 ‘H',
char * s 與 char a[ ] 的本質區(qū)別
當定義char a[10]的時候,編譯器會給數(shù)組分配10個單元,每個單元的數(shù)據(jù)類型都是字符,而定義char *s時,s是一個指針變量,只占4個字節(jié),32位,用來保存一個地址。
sizeof(a) = 10,sizeof(s) = 4
a的長度是10,s的長度是4,因為s是一個int型
printf("%p",s)----------這個表示 s 的單元中所保存的地址。
printf("%p",&s);--------這個表示變量本身所在內存單元地址。。。。,不要搞混了。。
總結:char * s 只是一個保存字符串首地址的指針變量,char a[]是許多連續(xù)的內存單元,單元中的元素是char型,char * 和 char a[]具有相同的效果,源于字符串的本質,即給一個字符串地址,便可以操作字符串,但char* 和 char a[]的本質屬性不一樣。
5、char ** 和char *a[]
char *a[]
[]的優(yōu)先級高于 * ,所以先是a[],它是一個數(shù)組,數(shù)組中的元素是char類型,char元素是一個變量,保存地址。
對于char *a[ ] = {“Dog”,“Cat”,“Chicken”};
數(shù)組中元素是字符串,sizeof(a)是12,并不是4+4+8,是因為字符串常量的本質是地址,a數(shù)組中元素是char *指針,指針變量是整數(shù)類型,占4個字節(jié),則3個元素就是12個字節(jié)。
char *a[] = { "Dog","Cat","Chicken" }; printf("%p %p %p \n", a[0], a[1], a[2]);
可以看到數(shù)組中的三個元素保存了三個內存地址,這三個地址代表了三個字符串的首地址,而不是字符串本身,且三個地址不是連續(xù)的,它是編譯器為"Dog",“Cat”,“Chicken” 分配的內存空間的地址,因此沒有關聯(lián)。
char *a[] = { "Dog","Cat","Chicken" }; printf("數(shù)組元素單元本身的地址:%p %p %p \n", &a[0], &a[1], &a[2]);//數(shù)組元素單元本身的地址
可以看到三個元素單元所在的地址是連續(xù)的,每個地址相差四個字節(jié)。
char ** s
char ** 為二級指針,s保存一級指針char *的地址,
例如:
char *a [ ] = { "Dog","Cat","Chicken" }; char **s = a;//---有問題
數(shù)組a代表數(shù)組元素內存單元的首地址,,即a = &a[0] = 010FFD44,即 *s = 001D6BE0 = “Dog”,
這樣可以通過s訪問a中的數(shù)據(jù)
printf(“%s”,*s); printf("%s",a[0]); printf("%s",*a);
三個一樣,,但是不能把a = s,因為a是一個常量;
char **s = “hello world”; ------是錯誤的;
因為s的類型是char ** ,而 “hello world”的類型是char *;
雖然都是地址, 但是指向的類型不一樣,因此,不能這樣用。,從其本質來分析,“Hello world”,代表一個地址,比如0x000001,這個地址中的內容是 ‘H',為char型,而s也保存一個地址,這個地址內容是char*,是一個指針類型。
char **s; *s = "hello world";
編譯沒有問題,但是 printf("%s",s),就會崩潰, printf ("%s", s); 時,首先得有s 保存的地址,再在這個地址中找到 char * 的地址,即*s;
若s = 0x1000;
在0x1000所在的內存單元保存了“hello world”的地址0x000001,*s = 0x000001,這樣printf("%s",*s)會先找到0x1000,然后找到0x000001,如果直接使用char **s,令 * s = “hello world”,s變量中保存的是一個無效隨機不可用的值,不知道他指向哪里,所以用char **s時,要給他分配一個內存地址。
char **s ; s = (char **) malloc(sizeof(char**)); *s = "hello world";
這樣s給分配了一個可用的地址,s = 0x1234,然后再地址0x1234所在的內存中的位置,保存了“hello world”的值。
下列程序中,定義了字符指針s,s中存放了字符串"message"的地址。
#include <stdio.h> void buf( char **s) { *s = "message"; } int main() { char *s ; buf(&s); printf("%s\n",s); }
即:二級指針保存的是一級指針的地址,它的類型就是指針變量,一級指針保存的是指向數(shù)據(jù)所在的內存單元的地址。
參考:
https://blog.csdn.net/daiyutage/article/details/8604720
6、C語言中char s[] 和 char *s的區(qū)別
有關于這兩者的區(qū)別,下面的來自Stack Overflow的解釋非常清晰:
http://stackoverflow.com/questions/1704407/what-is-the-difference-between-char-s-and-char-s-in-c
The difference here is that
char *s = "Hello world";
will place Hello world in the read-only parts
of the memory and making s a pointer
to that, making any writing operation
on this memory illegal
. While doing:
char s[] = "Hello world";
puts the literal string in read-only memory and copies the string to newly allocated memory
on the stack. Thus makings[0] = 'J' legal
.
總結一下,要點如下:
char []
定義的是字符串數(shù)組,該字符數(shù)組在內存中的存儲是先分配新空間,再去填充,因此該數(shù)組的內容可以改變,即通過s[0] = 'J'
是合法的。char *s
定義的是字符串指針變量,該指針變量指向一個字符串,該指針的值是該字符串在內存中的地址。對于這個指針變量來說,改變它的值=改變地址=改變指針指向,比如從指向第一個字符變?yōu)橹赶虻诙€字符。然后改字符指針變量并沒有權力去更改它指向的字符的值,比如*(s+1) = 'J'
。換句話說,就是可以修改指針的值,但不能修改指針指向的值。
到此這篇關于C語言char s[]和char* s的區(qū)別的文章就介紹到這了,更多相關C語言 char s[]和char* s內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
C++ 11 std::function和std::bind使用詳解
這篇文章主要介紹了C++ 11 std::function和std::bind使用詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-02-02C++ Qt實現(xiàn)瀏覽器網(wǎng)頁內嵌的音視頻播放器
這篇文章主要為大家詳細介紹了如何利用C++ Qt實現(xiàn)瀏覽器網(wǎng)頁內嵌的音視頻播放器,并支持軟硬解碼,支持音頻,支持錄像截圖,支持多路播放等,感興趣的可以了解下2024-01-01