簡體   English   中英

c中int指針和char指針之間有區別嗎?

[英]Are there differences between int pointer and char pointer in c?

我是 C 新手,無法理解指針。 我感到困惑的部分是關於char *int *

比如我們可以直接給char賦值一個指針,比如

char *c = "c"; 它不會出錯。

但是,如果我像剛才那樣為 int 分配一個指針,例如int * a = 10; ,

它會出錯。 我需要在內存中留出額外的空間來為 int 分配一個指針,

int *b = malloc(sizeof(int)); *b = 20; free(b); int *b = malloc(sizeof(int)); *b = 20; free(b); ...

誰能告訴我為什么?

我認為您誤解了指針是什么以及它的含義。 在這種情況下:

int* a = 10;

您是說“創建一個指針(指向int )並將其瞄准文字內存位置0x0000000A (10)。

這和這個不一樣:

int n = 10;
int* a = &n;

即“創建一個指針(指向int )並將其瞄准n的內存位置。

如果你想動態分配這個:

int* a = malloc(sizeof(int));
*a = 10;

這意味着“創建一個指針(指向int )並將其指向剛剛分配的內存塊,然后將值10分配給該位置

通常你從來沒有分配單個int ,你會分配其中一束用於陣列,在這種情況下,你把它稱為a[0]通過a[n-1]用於大小的數組n 在 C 中*(x + y)通常與x[y]相同,或者換句話說*(x + 0)只是*xx[0]

在您的示例中,您不會將c發送到字符'c' 您使用了"c" ,它是一個字符串字面量。 對於字符串文字,它的工作原理如https://stackoverflow.com/a/12795948/5280183 中所述

"c"這樣的字符串文字實際上是一個數組表達式( "c"的類型是“ char的二元數組”)。

除非它是sizeof&運算符的操作數,或者是用於在聲明中初始化字符數組的字符串文字,否則類型為“ T數組”的表達式將被轉換,或“衰減”為類型為“的表達式”指向T " 的指針,其值將是數組第一個元素的地址。

所以當你寫

char *c = "c"; 

它大致相當於寫作

char string[] = "c";
char *c = &string[0];

您正在為指針分配一個指針,因此編譯器不會抱怨。

然而,當你寫

int *a = 10;

您正在為指針分配一個int值並且類型不兼容,因此編譯器會抱怨。 指針不是整數; 它們可能有一個整數表示,但這不能保證,並且它的大小不會與int相同。

初始化時,右側 (RHS) 表達式必須屬於或可轉換為聲明的變量類型。

如果你這樣做

char *cp = ...
int *ip = ...

那么...必須可轉換為指向char指針指向int指針 還要記住, char是單個字符。

現在, "abc"是 C 中的特殊語法 - 字符串文字,用於創建(許多)不可變字符數組 它具有char [size]類型,其中size是文字中的字符數加上終止空字符的 1。 所以"c"類型是char [2] 它不是char C 中的數組被隱式轉換指向第一個元素的指針,然后具有“指向元素類型的指針”的類型。 "c"型的char [2]char *cp = "c"; 被隱式轉換為類型char * ,這點與第一兩個字符的c\\0兩字符陣列英寸它也是char *類型的方便,現在我們有char *cp = (something that has type char * after conversions); .

至於int * ,您正在嘗試將整數值傳遞給指針。 它沒有任何意義。

一個指針保存一個地址。 如果你要問夏洛克福爾摩斯的地址,答案是貝克街 221 號。 現在你所做的是“福爾摩斯的地址是我今天早上給他拍的這張照片”。

char *編寫的相同錯誤代碼將是

char *cp = 'c'; // or more precisely `char *p = (char)'c';

它會給你完全相同的錯誤證明char *cpint *cp工作方式相似。


不幸的是,C 沒有int字符串文字,也沒有整數數組的文字,但從 C99 開始,您可以編寫:

int *ip = (int[]){ 5 };

或者

const int *ip = (const int[]){ 5 };

同樣,您始終可以將char *int *指向該類型的單個對象:

字符 a = 'c'; 字符 *pa = &a; 整數 b = 42; int *pb = &b;

現在我們可以說a*pa指定相同的char對象a ,同樣b*pb指定相同的int對象b 如果您更改*pa您將更改a ,反之亦然; 對於b*pb也是如此。

c中int指針和char指針之間有區別嗎?

簡短回答:否

在過去的幾十年里,C 中的所有指針都是平等的。 由於一種稱為內存模型的東西,在某些平台(如 Windows)中,有一段時間存在不同大小的指針。

今天,編譯器根據平台將代碼設置為使用 32 位或 64 位或任何大小的指針,但一旦設置,所有指針都相等。

不相等的是指針指向的東西,是你困惑的地方。

  • 考慮一個void*指針。 malloc()在 C 中分配內存。它總是返回一個void*指針,然后你把它轉換成你需要的任何東西
  • sizeof(void*)sizeof(int*) sizeof(GiantStruct*) ,在 64 位編譯器中為 8 字節或 64 位

char* c = "c" 怎么樣?

  • 你必須問自己什么是"c" char[2] 它是一個字符串文字。 在內存中的某個地方,系統將分配至少 2 個字節的區域,在那里放置一個'c'和一個零,因為字符串文字在C中以NULL結尾,將該地址放入分配給您的指針c的地址中。

int* a = 10呢?

  • 這是同一回事。 直到操作系統自帶的,是有點ok了。什么是a 一個是int*指針,指向一個int 什么是*a 一個int 在哪個地址? 10 . 好吧,事實是系統不會讓您訪問該地址,因為您設置了一個指向該地址的指針。 在 80 年代,你可以。 今天對此有非常嚴格的規則:您只能訪問分配給您的進程的內存。 僅有的。 因此,一旦您嘗試訪問,系統就會中止您的程序。

一個例子

如果你寫

    int* a = malloc(300);

系統會分配一個300字節的區域,把區域地址給你寫在分配給a的地址上。 當您寫入*a=3456 ,系統會將這個值寫入該地址的第一個sizeof(int)字節。

您肯定可以寫出所有 300 個,但您必須稍微操縱指針以指向該區域內。 只在那個區域里面。 事實上,C 語言就是為此而設計的。

讓我們在分配給 a 的 300 字節區域的末尾寫入“c”:

#include <stdio.h>
#include <stdlib.h>
int main(void)
{
    char* c = "c";
    int* a = (int*)malloc(300);
    *a = 3456;
    printf("Area content is %d\n", *a);
    char* pToEnd = (char*)a + 298;
    *(pToEnd) = 'c';
    *(pToEnd + 1) = 0;
    printf("At the end of the 300-byte area? [Should be 'c'] '%s'\n", pToEnd);
    printf("The pointer c points to '%s'\n", c);
    //*c = 'x'; // error: cancel program
    c = pToEnd;
    printf("The pointer c now points do the end of the 300-byte area:'%s'\n", c);
    free(a);
    return 0;
};

看看

Area content is 3456
At the end of the 300-byte area? [Should be 'c'] 'c'
The pointer c points to 'c'
The pointer c now points do the end of the 300-byte area:'c'

另請注意,一旦您嘗試覆蓋c ,即示例中的char指針,您的程序也將取消。 它是一個只讀區域 --- 請參閱第 14 行的注釋。但是您可以在示例中將c指向該區域內並使用它,因為指針本身不是常量。

當您在上面的示例中編寫c = pToEnd時,對字符串文字的訪問將永遠丟失。 從某種意義上說是內存泄漏,但它是靜態分配的區域。 泄漏的不是區域而是地址。

還需要注意的是free(a)到了最后,即使是a int*將釋放所有300個字節

您的問題的直接答案是, C語言是一種嚴格類型的語言。 在生成機器碼之前,編譯器會檢查一些可能的錯誤。 類型不同,這就是編譯器想要知道的全部內容。

但是從bit-byte來看,沒有區別,對於C語言來說,跟上面兩個指針沒有區別。

使用在線編譯器查看您的代碼

void main(){
 int * a = 10; /* <= this presumably gives you an error. */
}

我所做的是復制粘貼你的代碼,給你帶來錯誤。 並且在線編譯器發出了警告,而不是錯誤。 甚至更多。 C標准更改為c17 ,您仍然c17收到警告。

關於將字符串文字分配給指針的注意事項已在 SO 上進行了廣泛討論。 它值得一個不同的話題。

把它們加起來。 對於C語言,上述兩個指針沒有任何意義。 用戶有責任了解他/她程序中的內存布局。 總而言之,該語言被設計為一種在線性內存上運行的高級工具。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM