2009-03-03 74 views
8

試圖瞭解如何解決字符串數組中的單個字符問題。另外,這當然會讓我理解一般指針下標的指針。 如果我有char **a並且我想要達到第二個字符串的第三個字符,這是否工作:**((a+1)+2)?似乎應該...如何從c中的字符串數組訪問單個字符?

回答

19

幾乎,但不完全。正確的答案是:

*((*(a+1))+2) 

,因爲你需要先取消參照實際字符串指針之一,然後你去參考所選字符串指針到所需的字符。 (請注意,爲了使操作順序更清晰,我添加了額外的括號)。

另外,這個表達式:

a[1][2] 

還將努力....也許會被優選的,因爲你正在嘗試做的目的是更加不言自明,並且註釋本身更簡潔! 。這種形式可能不會立即對新語言的人顯而易見,但要明白數組符號工作的原因是因爲在C中,數組索引操作實際上只是等效指針操作的簡寫。即:*(a + x)與a [x]相同。因此,通過將該邏輯擴展到原始問題,有兩個單獨的指針去引用操作級聯在一起,從而表達式a [x] [y]等價於*((*(a + x))+ Y)。

+0

因此,指針指針可以作爲一個數組使用,而不需要任何其他聲明? – sdellysse 2009-03-03 15:43:57

+0

我會+1,如果你解釋爲什麼。 – 2009-03-03 15:44:21

1

嘗試a[1][2]。或者*(*(a+1)+2)

基本上,數組引用是用於指針解引用的語法糖。 a [2]與a + 2相同,也與2 [a]相同(如果您確實需要無法讀取的代碼)。字符串數組與雙指針相同。所以你可以使用[1]或*(a+1)來提取第二個字符串。然後,您可以使用b [2]或*(b + 2)找到該字符串中的第三個字符(現在稱爲'b')。用原來的第二個字符串替換'b',我們最終得到[1] [2]或者*(*(a+1)+2)

2

IIRC,一個字符串實際上是字符數組,所以這應該工作:

a[1][2] 
3

您不必使用指針。

INT主(INT的argc,焦炭** argv的){

的printf( 「 的argv [1]的第三個字符爲[%C]。\ n」 個,的argv [1] [2 ]);

}

然後:

$ ./main你好 的argv [1]的第三個字符是[1]。

這是一個和一個l。

你可以使用指針,如果你想...

*(的argv [1] +2)

甚至

*((*(A + 1))+ 2)

正如有人在上面指出。

這是因爲數組名稱是指針。

2

上C指針從維基百科article行情 -

在C,數組索引在指針運算方面正式定義;即 語言規範要求數組[i]等於*(數組+ i)。因此,在C中,可以將數組看作指向連續內存區域的指針(沒有間隙),並且訪問數組的語法與可用於取消指針的指針的語法相同。例如,數組可以聲明,並以下列方式使用:

int array[5];  /* Declares 5 contiguous (per Plauger Standard C 1992) integers */ 
int *ptr = array; /* Arrays can be used as pointers */ 
ptr[0] = 1;  /* Pointers can be indexed with array syntax */ 
*(array + 1) = 2; /* Arrays can be dereferenced with pointer syntax */ 

所以,針對您的問題 - ,指針的指針,可以在使用數組沒有任何其他聲明所有!

1

Theres在討論指針,字符串,討論指針,字符串,僅供編程解釋部分值得一提的黑客攻擊的藝術第2版第2版的一個輝煌的C編程解釋https://leaksource.files.wordpress.com/ 2014/08 /黑客先進-的-exploitation.pdf。

儘管問題已經得到解答,但其他人想要了解更多信息,可能會發現埃裏克森書中的以下亮點有助於理解問題背後的一些結構。

頭可供您可能會使用變量操縱頭文件

例子。

stdio.h中 - http://www.cplusplus.com/reference/cstdio/

stdlib.h中 - http://www.cplusplus.com/reference/cstdlib/

字符串。^h - http://www.cplusplus.com/reference/cstring/

limits.h中 - http://www.cplusplus.com/reference/climits/

功能

您可能會使用的通用功能的示例。

的malloc() - http://www.cplusplus.com/reference/cstdlib/malloc/

釋放calloc() - http://www.cplusplus.com/reference/cstdlib/calloc/

strcpy() - http://www.cplusplus。COM /參考/:字符串/的strcpy/

存儲器

編譯的程序的存儲器被劃分成五個段:文本,數據,BSS,堆,並且堆疊中的每個段代表的存儲器中的特殊部該文本段有時也被稱爲代碼段,這是程序的彙編機器語言指令所在的位置「」。

的指令在該段中的執行是非線性的,由於上述的高級別控制的結構和功能,該編譯 成分支,跳轉,並調用在彙編語言指令。作爲一個程序 執行時,所述EIP被設置爲在所述文本段中的第一條指令然後 處理器如下的執行循環,執行以下操作:

1.讀取EIP指向

」的指令 2.添加指令的字節長度EIP

3.執行將在步驟讀取的所述指令1

4.返回到步驟1

有時,指令將是跳轉或調用指令,其中 將EIP更改爲不同的內存地址。處理器並不在意 ,因爲它預計執行非線性 無論如何。如果在步驟3中更改了EIP,則處理器將返回到步驟1並讀取在任何EIP更改爲

的地址中找到的指令,在文本段中禁用寫入權限,如它不用於存儲變量,只用於存儲代碼。這可以防止人們實際修改程序代碼;任何試圖寫入這段內存的嘗試都會導致程序提醒用戶發生了一些不好的事情,並且程序 將被終止。此段爲只讀的另一個優點是它可以在程序的不同副本之間共享,允許多個程序同時執行而不會有任何問題。應該 還指出,這種內存段具有固定的大小,因爲沒有在以往 改變它

的數據和BSS段用於存儲全局和靜態程序 變量。數據段填充了初始化的全局變量和靜態變量,而bss段則填充了未初始化的對象。雖然這些段是可寫的,但它們也具有固定大小。請記住,全局變量仍然存在,儘管有功能上下文(如前面例子中的變量j)。全局和靜態變量能夠繼續存在,因爲它們存儲在自己的內存段

堆段的內存段程序員可以直接 控制。無論程序員可能需要什麼,該段中的內存塊都可以分配並用於 。關於堆 段的一個值得注意的問題是,它不是固定的大小的,因此它可以成長根據需要更大或更小「

所有堆內的存儲器是由分配器和釋放器算法管理,它們分別在堆中預留一個區域以供使用並移除保留以允許該部分內存被重新用於稍後的保留。堆將會增長和縮小,取決於如何保留大量內存以供使用。這意味着使用堆分配函數的程序員可以動態地保留和釋放內存。堆向下朝更高的存儲器移動的 生長地址

堆棧段還具有可變的大小,並且被用作臨時高速暫存存儲期間函數調用本地函數變量和上下文。這就是GDB的回溯命令所看到的。當一個程序調用一個函數時,該函數將擁有自己的一組傳遞變量,並且該函數的代碼將位於文本(或代碼)段中的不同存儲位置。由於上下文和EIP在調用函數時必須更改,因此堆棧用於記住所有傳遞的變量,EIP在函數完成後應返回的位置以及該函數使用的所有局部變量。所有這些信息一起存儲在堆棧中,統稱爲堆棧幀。該堆棧包含許多堆棧幀

在通常的計算機科學術語中,堆棧是經常使用的抽象數據結構。它有先入先出(FILO)訂購 ,這意味着放入堆棧的第一個項目是最後一個項目。把它看作是把珠子放在一端有一個結的繩子上 - 直到你去除了所有其他珠子後,你才能得到第一個珠子。當一個項目被放入棧,它被稱爲推,當一個項目從堆棧中刪除,這就是所謂的爆裂

顧名思義,內存堆棧段,實際上,一個包含堆棧幀的堆棧數據結構。 ESP寄存器用於跟蹤堆棧結束的地址,堆棧的結束地址隨着項目被推入並彈出而不斷變化。由於這是非常動態的行爲,因此棧的大小也不是固定的。相反的堆的動態增長,作爲堆棧改變 S IN的大小,它向上在存儲器的視覺列表,向較低存儲器生長地址

堆疊的FILO性質似乎奇,但由於堆棧使用 來存儲上下文,所以它非常有用。當一個函數被調用時,有幾件事物會在堆棧框架中一起推入堆棧。 EBP寄存器 - 有時稱爲幀指針(FP)或本地基址(LB)指針 - 用於引用當前堆棧幀中的本地函數變量。每個堆棧幀都包含函數的參數,其局部變量以及兩個指針,這兩個指針用於重新設置它們的方式:保存的幀指針(SFP)和返回地址。SFP用於將EBP恢復到先前的值,並使用返回地址 將EIP恢復到函數調用後發現的下一條指令。此恢復先前的堆棧幀 的功能上下文「

字符串

在C中,一個陣列是一個簡單的特定數據類型的n個元素的列表。一個20字符的數組只是位於內存中的20個相鄰字符。陣列也被稱爲緩衝器

#include <stdio.h> 

int main() 
{ 
    char str_a[20]; 
    str_a[0] = 'H'; 
    str_a[1] = 'e'; 
    str_a[2] = 'l'; 
    str_a[3] = 'l'; 
    str_a[4] = 'o'; 
    str_a[5] = ','; 
    str_a[6] = ' '; 
    str_a[7] = 'w'; 
    str_a[8] = 'o'; 
    str_a[9] = 'r'; 
    str_a[10] = 'l'; 
    str_a[11] = 'd'; 
    str_a[12] = '!'; 
    str_a[13] = '\n'; 
    str_a[14] = 0; 
    printf(str_a); 
} 

在前面的程序,一個20元件的字符數組被定義爲 str_a,並且陣列中的每個元素被寫入,一個接一個。請注意,數字從0開始,而不是1.還要注意最後一個字符是0「。

(這也稱爲空字節。)字符數組已定義,因此20個字節被分配給它,但實際上只使用了其中的12個字節。最後的空字節編程被用作分隔符來告訴正在處理字符串的任何函數在那裏停止操作。剩餘的額外字節只是垃圾,將被忽略。如果一個空字節插入於字符數組的第五元件,只有字符你好將由printf()函數打印「

由於在字符數組設置每個字符是艱苦和字符串是經常使用,爲字符串操作創建了一組標準函數。例如,strcpy()函數會將一個字符串從源複製到目的地,遍歷源字符串並將每個字節複製到目標(並在複製空終止字節後停止)

函數參數的順序與英特爾彙編語法目的地首先和源代碼相似。可以使用strcpy()重寫char_array.c程序,以使用字符串庫完成相同的操作。如下圖所示CHAR_ARRAY程序的下一個版本包括string.h中,因爲它使用一個字符串函數」。

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

int main() 
{ 
    char str_a[20]; 
    strcpy(str_a, "Hello, world!\n"); 
    printf(str_a); 
} 

發現C字符串的更多信息

http://www.cs.uic.edu /~jbell/CourseNotes/C_Programming/CharacterStrings.html

http://www.tutorialspoint.com/cprogramming/c_strings.htm

指針

EIP寄存器是一個指針,它在程序執行過程中通過包含其內存地址來」指向「當前指令。指針的想法也在C中使用。由於物理內存不能實際移動,因此必須複製其中的信息。複製大塊內存以供不同功能或不同地方使用時,計算起來可能非常昂貴。從內存的角度來看,這也很昂貴,因爲在複製源之前必須保存或分配新目標副本的空間。指針是解決這個問題的方法。而不是複製一大塊內存,要繞過該塊內存的開始地址要簡單得多。「

C中的指針可以像任何其他變量類型一樣定義和使用。由於x86架構上的內存使用32位尋址,所以指針的大小也是32位(4字節)。指針通過在變量名前添加一個星號(*)來定義。一個指針定義爲指向該類型數據的東西,而不是定義該類型的變量。 pointer.c程序是一個與char數據類型一起使用的指針示例,該數據類型的大小僅爲1byte,大小爲「。

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

int main() 
{ 
    char str_a[20]; // A 20-element character array 
    char *pointer; // A pointer, meant for a character array 
    char *pointer2; // And yet another one 
    strcpy(str_a, "Hello, world!\n"); 
    pointer = str_a; // Set the first pointer to the start of the array. 
    printf(pointer); 
    pointer2 = pointer + 2; // Set the second one 2 bytes further in. 
    printf(pointer2); // Print it. 
    strcpy(pointer2, "y you guys!\n"); // Copy into that spot. 
    printf(pointer); // Print again. 
} 

作爲代碼中的註釋表明,第一個指針設置爲字符數組的開始。當字符數組這樣的引用,它實際上是一個指針本身。這是如何緩衝區被作爲一個指針傳遞給printf()和strcpy()函數,第二個指針設置爲第一個指針地址加上兩個,然後打印一些東西(如下面的輸出所示)「。

[email protected]:~/booksrc $ gcc -o pointer pointer.c 
[email protected]:~/booksrc $ ./pointer 
Hello, world! 
llo, world! 
Hey you guys! 
[email protected]:~/booksrc $ 

運算符-的地址通常與指針一起使用時,因爲指針包含存儲器地址。該addressof.c程序演示 操作者的地址被用來放的整數變量的地址 放入一個指針中。該行以粗體顯示在之下「。

#include <stdio.h> 

int main() 
{ 
    int int_var = 5; 
    int *int_ptr; 
    int_ptr = &int_var; // put the address of int_var into int_ptr 
} 

一個額外的單目運算符稱爲引用操作存在的指針,而此操作將返回指針所指向的地址找到的數據,而不是地址本身。它採用的形式變量名前面的星號,類似於指針的聲明。再一次,解引用運算符同時存在於GDB和C「。

數增加的addressof.c代碼(addressof2.c示出)將 表明所有的這些概念。所添加的printf()的函數使用格式 參數,我將在下一節中解釋目前,只關注程序輸出「。

#include <stdio.h> 

int main() 
{ 
    int int_var = 5; 
    int *int_ptr; 
    int_ptr = &int_var; // Put the address of int_var into int_ptr. 
    printf("int_ptr = 0x%08x\n", int_ptr); 
    printf("&int_ptr = 0x%08x\n", &int_ptr); 
    printf("*int_ptr = 0x%08x\n\n", *int_ptr); 
    printf("int_var is located at 0x%08x and contains %d\n", &int_var, int_var); 
    printf("int_ptr is located at 0x%08x, contains 0x%08x, and points to %d\n\n", &int_ptr, int_ptr, *int_ptr); 
} 

當一元運算符是具有指針使用時,操作者的-的地址可以被認爲是向後移動,而引用操作中指針指向方向向前移動」。

瞭解更多有關指針與內存分配

丹教授希爾施貝格,計算機科學系,在計算機存儲器加州大學https://www.ics.uci.edu/~dan/class/165/notes /memory.html

http://cslibrary.stanford.edu/106/

http://www.programiz.com/c-programming/c-dynamic-memory-allocation

陣列

一個叫亞歷克斯·阿蘭可以在這裏http://www.cprogramming.com/tutorial/c/lesson8.html

CHAP即使世界上多維數組的一個簡單的教程 由一位名叫章對數組

即使世界信息託德阿吉布森可在這裏http://www.augustcouncil.com/~tgibson/tutorial/arr。HTML

迭代數組

#include <stdio.h> 

int main() 
{ 

    int i; 
    char char_array[5] = {'a', 'b', 'c', 'd', 'e'}; 
    int int_array[5] = {1, 2, 3, 4, 5}; 
    char *char_pointer; 
    int *int_pointer; 
    char_pointer = char_array; 
    int_pointer = int_array; 

    for(i=0; i < 5; i++) { // Iterate through the int array with the int_pointer. 
     printf("[integer pointer] points to %p, which contains the integer %d\n", int_pointer, *int_pointer); 
     int_pointer = int_pointer + 1; 
    } 

    for(i=0; i < 5; i++) { // Iterate through the char array with the char_pointer. 
     printf("[char pointer] points to %p, which contains the char '%c'\n", char_pointer, *char_pointer); 
     char_pointer = char_pointer + 1; 
    } 

} 

鏈表VS陣列

數組不是唯一的選擇,在鏈表的信息。

http://www.eternallyconfuzzled.com/tuts/datastructures/jsw_tut_linklist.aspx

結論

此信息寫入簡單地傳遞一些什麼我已經在我的研究閱讀這個話題可能會幫助別人。

相關問題