c++ 拾遺

來源:互聯網
上載者:User
  1. typedef的用法

typedef的作用是真正意義上地定義一種別名,而不是一種簡單的宏替換。

typedef 與 #define的區別:

案例一:

通常講,typedef要比#define要好,特別是在有指標的場合。請看例子:

typedef char *pStr1;

#define pStr2 char *;

pStr1 s1, s2;

pStr2 s3, s4;
在上述的變數定義中,s1、s2、s3都被定義為char *,而s4則定義成了char,不是我們所預期的指標變數,根本原因就在於#define只是簡單的字串替換而typedef則是為一

個類型起新名字。

注意語句char* pa,pb; 其中pa定義成了一個字元指標,而pb則是定義成了一個字元變數。這個問題我一直沒有注意過,對於int來說,是一樣的,比如int *a,b實際定義了一個指標和一個整型數。所以好的編程習慣應該是將*與變數名串連在一起,而不是緊跟在類型後。比如:char *pa, pb;這個就比較一目瞭然了。  

再考慮這個問題:

下面的代碼中編譯器會報一個錯誤,你知道是哪個語句錯了嗎?

typedef char * pStr;

char string[4] = "abc";

const char *p1 = string;

const pStr p2 = string;

p1++;

p2++;

答案是:p2++會報錯。

const char *p1 = string 意思是說一個指向const char類型的指標。。
p1指標是一個變數。他可以指向任意的char對象。就算不是const定義的char也可以,p1可以指向不同的char對象,因為他是一個變數。但他無論是指向const char對象還是char對象。都不能改變其指向對象的值。就是說上例子p1不能對string做修改。只能讀取string的值。

typedef char *pStr
const pStr p2 = string 這裡是typedef和指標共用時的坑爹指出。
const pStr p2 = string
pStr const p2 = string
char* const p2 = string 上面3個語句是一個意思。
就是說p2是一個指向非const、char類型的對象的const指標。p2初始化之後就不能夠指向第二個對象。但p2可以對string的值進行修改。

對於用typedef定義函數指標別名的格式,以前自己沒有見過,有必要看看。

typedef void(*SIG_TYPE)(int); 定義了一個函數指標SIG_TYPE,函數的傳回型別是void,參數為int。

    2.   關於指標。 轉載一篇別人的文章。

指標是C語言的精華,它是一柄“雙刃劍”,用的好與壞就看使用者的功力了。下面就一道面試題,看一下指標與數組的區別。

char *p1, *p2;
char ch[12];
char **pp;
p1 = ch;
pp = &ch;
p2 = *pp;
問p1和p2是否相同

    題目如上,找出其中的不妥之處。

    首先,數組ch是沒有初始化的。其次,一個比較隱含的地方是,數組名可以代表數組第一個元素的首地址,這個沒有問題,但是,數組名並非一個變數,數組分配 完成後,數組名就是固定的,地址也是固定的。這樣導致的結果就是絕對不能把數組名當作變數來進行處理。上述題目中,pp=&ch,顯然是把數組名 當作指標變數來使用了,這樣肯定出問題。

    這個題目存在的兩個問題,第一個問題比較簡單,可以認為是粗心大意。但是第二個問題就是相當複雜了,擴充開來,那就是C語言中的精華中的指標和數組的聯絡 與區別問題了。

    下面分為兩步,首先看一下指標和數組的區別方法,然後提出對上述程式的修改方案。

1 指標和數組的區別

(1)指標和數組的分配

    數組是開闢一塊連續的記憶體空間,數組本身的標識符(也就是通常所說的數組名)代表整個數組,可以使用sizeof來獲得數組所佔據記憶體空間的大小(注意, 不是數組元素的個數,而是數組佔據記憶體空間的大小,這是以位元組為單位的)。舉例如下:

#include <stdio.h>
int main(void)
{
char a[] = "hello";
int b[] = {1, 2, 3, 4, 5};
printf("a: %d\n", sizeof(a));
printf("b memory size: %d bytes\n", sizeof(b));
printf("b elements: %d\n", sizeof(b)/sizeof(int));
return 0;
}

    數組a為字元型,後面的字串實際上佔據6個位元組空間(注意最後有一個\0標識字串的結束)。從後面sizeof(b)就可以看出如何獲得數組佔據的內 存空間,如何獲得數組的元素數目。至於int資料類型分配記憶體空間的多少,則是編譯器相關的。gcc預設為int類型分配4個位元組的記憶體空間。

(2)空間的分配

    這裡又分為兩種情況。

    第一,如果是全域的和靜態
    char *p = “hello”;
    這是定義了一個指標,指向rodata section裡面的“hello”,可以被編譯器放到字串池。在彙編裡面的關鍵字為.ltorg。意思就是在字串池裡的字串是可以共用的,這也是 編譯器最佳化的一個措施。
    char a[] = “hello”;
    這是定義了一個數組,分配在可寫資料區塊,不會被放到字串池。

    第二,如果是局部的
    char *p = “hello”;
    這是定義了一個指標,指向rodata section裡面的“hello”,可以被編譯器放到字串池。在彙編裡面的關鍵字為.ltorg。意思就是在字串池裡的字串是可以共用的,這也是 編譯器最佳化的一個措施。另外,在函數中可以返回它的地址,也就是說,指標是局部變數,但是它指向的內容是全域的。
    char a[] = “hello”;
    這是定義了一個數組,分配在堆棧上,初始化由編譯器進行。(短的時候直接用指令填充,長的時候就從全域字串表拷貝),不會被放到字串池(同樣如前,可 能會從字串池中拷貝過來)。注意不應該返回它的地址。

(3)使用方法

    如果是全域指標,用於不需要修改內容,但是可能會修改指標的情況。
    如果是全域數組,用於不需要修改地址,但是卻需要修改內容的情況。
    如果既需要修改指標,又需要修改內容,那麼就定義一個數組,再定義一個指標指向它就可以了。

2 我編寫的修改方案

[armlinux@lqm pointer]$ cat pointer.c
/*
* Copyright 2007 (c), Shandong University
* All rights reserved.
*
* Filename : test.c
* Description: about pointer
* Author : Liu Qingmin
* Version : 1.0
* Date : 2007-08-27
*/
#include <stdio.h>
/*
* define a macro which is used to debug array mode and pointer mode.
* if 1, debug array mode; else debug pointer mode.
* You can change it according to your decision.
*/
#define ARRAY_OR_POINTER 0
int main(void)
{
char *p1;
char *p2;
char **pp;
//test1
#if ARRAY_OR_POINTER
char ch[] = "hello, world!\n";
printf("%d, %d, %d, %d\n", sizeof(p1), sizeof(p2),
sizeof(pp), sizeof(ch));
#else
char *ch = "hello, world!\n";
printf("%d, %d, %d, %d\n", sizeof(p1), sizeof(p2),
sizeof(pp), sizeof(ch));
#endif
//test2
        p1 = ch;
#if ARRAY_OR_POINTER
                pp = &p1;
#else
                pp = &ch;
#endif
        p2 = *pp;
if (p1 == p2) {
printf("p1 equals to p2\n");
} else {
printf("p1 doesn't equal to p2\n");
}
return 0;
}

    執行結果如下:

// ARRAY_OR_POINTER為0時
[armlinux@lqm pointer]$ ./test
4, 4, 4, 4
p1 equals to p2
// ARRAY_OR_POINTER為1時
[armlinux@lqm pointer]$ ./test
4, 4, 4, 15
p1 equals to p2

    如果使用了數組定義方式,而又使用pp=&ch,那麼就會出現類似下面的錯誤:

[armlinux@lqm pointer]$ make
gcc -Wall -g -O2 -c -o pointer.o pointer.c
pointer.c: In function `main':
pointer.c:44: warning: assignment from incompatible pointer type
gcc -Wall -g -O2 pointer.o -o test
[armlinux@lqm pointer]$ ./test
4, 4, 4, 15
p1 doesn't equal to p2

主要就是,數組定義時,數組名的類型應該是char (*)[12],這個與char**是有區別的。所以如果需要對數組名進行其他動作的話,最好先用一個指標承接。

    3.   struct的儲存空間大小

一般按照四位對齊,不及四位的話會補齊。

    4.   函數指標

下面程式中關於函數指標的使用都是合法的。

#include <iostream>
using namespace std;
float f(const float&);
int main()
{
typedef float (*PFUN)(const float &);
PFUN p1 = f;
PFUN p2 = &f;
cout<<p1(1)<<endl;
cout<<(*p1)(1)<<endl;
cout<<p2(1)<<endl;
cout<<(*p2)(1)<<endl;
}
float f(const float& a)
{
return a+1;
}
程式的輸出為:
2
2
2
2

 

如何返回指向函數的指標呢?比如: int (*ff(int)) (int *,int );在這個,ff是一個函數,它有一個int類型的形參,返回一個指向函數的指標。指標指向的函數傳回值為int類型,接受一個int*型和一個int型的形參。這個表達看上去比較複雜,可以使用typedef簡化:typedef int (*PF)(int*,int);PF ff(int);

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.