解析C/C++指針、函數、結構體、共用體
指針
變量與地址
變量給誰用的?
變量是對某一塊空間的抽象命名。
變量名就是你抽象出來的某塊空間的別名。
指針就是地址。指向某個地址。
指針與指針變量
指針是指向某塊地址。指針(地址)是常量。
指針變量是可以發生變化的。
#include <stdio.h> int main() { int i = 1; int *p = &i; printf("i = %d \n", i); printf("&i = %p \n", &i); printf(" p = %p \n", p); printf("&p = %p \n", &p); printf("*p = %d \n", *p); // 為什麼不用char* p = &i; //TYPE NAME = VALUE //int* p = &i; //int i = 1; }
直接訪問間接訪問
占內存空間
都是8字節,linux 64 位中。
空指針 野指針 空類型
int * i= NULL;
指針運算
兩個指針同時指向一個數組。++ 、–、比較、關系、&、*
指針與一維數組
數組名和 指針的區別?
a是數組名字是一個表示地址的常量。
指針是一個變量。
a++;
p++;
#include <stdio.h> int main() { int a[3] = {1,2,3}; int *p = a; int i; for(i = 0;i < sizeof(a)/sizeof(*a); i++) { printf("%d %d %d %d \n",a[i],*(a+i),p[i],*(p+i)); // a[i] printf("%p %p %p %p \n",a+i, &a[i],p+i, p+i); // &a[i] } printf("\n"); }
這裡代碼體現什麼是指針常量什麼是指針變量?
#include <stdio.h> int main() { int a[3]; int i; int *p = a; for(i = 0;i < sizeof(a)/sizeof(*a); i++) { printf("%p -> %d\n",&a[i],a[i]); } for(i = 0;i <sizeof(a)/sizeof(*a); i++) { scanf("%d",p++); //p = a; for(i = 0;i < sizeof(a)/sizeof(*a); i++,p++) { printf("%p -> %d\n",p,*p); printf("\n"); }
指針與二維數組
#include <stdio.h> #include <stdlib.h> int main() { int a[2][3] = {1,2,3,4,5,9}; int i,j; int *p; //(W) p = a; //wall等號右邊a是在行間跳轉的指針 // 等號左邊是列間跳轉的指針 p = *(a+0); //p = &a[0][0];//*(a+0),*a; printf("%p->%p \n", a, a + 1); // printf("%p -> %d \n\n",p,*p); // for(i = 0; i < 6; i++,p++) { // printf("%d ",*p); // } // printf("\n"); for(i = 0;i < 2; i++) { for(j = 0; j < 3; j++) { printf("%p->%d\n",&a[i][j],a[i][j]); printf("%p->%d\n",*(a+i)+j,*(*(a+i)+j)); //printf("%p->%d\n",a[i]+j,*(*(a+i)+j)); //printf("%d ",a[i][j]); } printf("\n"); } exit(0); }
指針與字符數組
#include <stdio.h> #include <stdlib.h> #include <string.h> // 字符指針和字符數組之間的使用 // // 練習 定義數組後定義指針 後面操作都用指針實現 int main() { #if 0 char* str = "hello"; // "hello" 串常量 printf("%d %d \n",sizeof(str),strlen(str));// 8 5 //strcpy(str,"world"); //err 為什麼不可以?區分字符指針和字符數組的區別 :企圖用"world" 覆蓋串常量 str = "world"; puts(str); #endif char str[] = "hello"; printf("%d %d \n",sizeof(str),strlen(str));// 6 5 // (F) str = "hhhh"; // 數組名是一個地址常量怎麼可能放到等號左邊??? strcpy(str,"jjjj"); char str[] = "hello world"; char *p = str + 7; puts(p); exit(0); }
const與指針
#include <stdio.h> #include <stdlib.h> /* 常見const const int a; int const a; const int *p; // 常量指針 int const *p; int *const p; // 指針常量 const int *const p; define 不檢查語法 */ int main() { #if 0 // cosnt修飾常規變量的使用特點 // 這個警告已經構成error const float pi = 1.14159; // pi = 9999.2; float *p = π // initialization discards ‘const' qualifier from pointer target type [enabled by default] *p = 1223.333333; // 修改方法 const float *p = π printf("%f\n",pi); // 1223.333333 printf("%f\n",*p); #endif // 常量指針:指針的指向可以發生變化但是指針所指向的目標值是不能變化的 // const *p // 值不能變 // 指向可以發生變化 int i = 1; const int *p1 = &i; int j = 88; //T i= 10; //F *p1 = 99; //T p1 = &j; printf("%d\n",i); printf("%d\n",*p1); // 指針常量:指針的指向不能發生變化,指針所指向的目標變量的值可以發生變化。 int j= 100; int * const p1 = &i; //T *p1 = 10; //F p1 = &j; //const 左右都有 指向和值都不能變 int num = 10; const int* const p3 = # // *p3 = 99; // p3 = &i; exit(0); }
指針數組和數組指針的區別
數組指針
#include <stdio.h> #include <stdlib.h> /* 數組指針: [存儲類型] 數據類型 (* 指針名) [下標] = 值; int (*p)[3]; -> type name; -> int[3] *p; */ int main() { // 數組指針 int a[2][3] = {1,2,3,4,5,9}; int i,j; int *p = *a; int (*q)[3] = a; //printf("%d \n", *a); // a[0][0]的地址 //printf("%d \n", **a); //1 #if 0 // printf("%d \n",*p);//q //int *p = *a; //printf("%d \n",*p); //q // int (*q)[3] = a+1; // printf("%d \n",**q); // 4 printf("\n"); for(i = 0;i < 2; i++) { for(j = 0; j < 3; j++) { // printf("%p->%d\n",*(a+i)+j,*(*(a+i)+j)); printf("%p->%d\n",*(q+i)+j,*(*(q+i)+j)); } printf("\n"); } #endif }
指針數組:
#include <stdio.h> #include <stdlib.h> #include <string.h> /* int *arr[3]; -> TYPE NAME; -> int *[3] arr; */ int main() { char *name[5] ={"english","math","cpp","teacher","computer"}; int i,j; for(i = 0; i < 5; i++) { puts(name[i]); } for(i = 0; i < 5 ;i++) { int k = i; for(j = i+1;j < 5; j++) { if(strcmp(name[k],name[j]) > 0) { k = j; } } if(k != i) { char *tmp = name[i]; name[i] = name[k]; name[k] = tmp; printf("排序後:\n"); exit(0); }
指針和函數
函數:
echo $? // 顯示上個命令的返回值
#include <iostream> using namespace std; /* run this program using the console pauser or add your own getch, system("pause") or input loop */ /* 定義: int a[N] = {1,2,3,4,5,6}; int *p = a; -> a *a a[0] &a[3] p[i] p *p p+1 -> int* int int int * int int* int int* */ //void func1(int *a,int n) void func1(int* a,int n,int *b) { cout << "== b =" << *b<< endl; // 1 for(int i = 0;i < n; i++) { printf("%d ",*(a+i)); } printf("\n"); return ; } int main(int argc, char** argv) { int arr[3] = {1,2,3}; func1(arr,3,&arr[1]);//&(*(ar+1)) return 0;
用指針與一維數組的使用:
void func2(int *p,int n) { int m = n / 2; for(int i = 0;m--;i ++) { int j = n - i -1; int tmp = *(p+i); *(p+i) = *(p+j); *(p+j) = tmp; } } int main(int argc, char** argv) { int arr[] = {1,2,3,6,4,2,38,4,2,23}; //func1(arr,3,&arr[1]);//&(*(ar+1)) func2(arr,10); for(int i = 0;i < 10;i ++) cout << arr[i] << ' ' ; cout <<endl; return 0;
函數與二維數組:
#include <iostream> using namespace std; /* run this program using the console pauser or add your own getch, system("pause") or input loop */ /* int a[M][N] = {......}; int *p = a; int (*q)[N] = a; -> a[i][j] *(a+i) a[i]+j p[i] *p int int * int * int int -> q[i][j] *q q p+3 q+2 int int* int(*)[N] int * int (*)[N] */ void func(int *p,int n) { for(int i = 0;i < n; i++) { cout << *p << ' '; p++; } } void print_arr(int (*p)[3]) for(int i = 0;i < 3;i++) for(int j = 0;j < 3;j++) { cout << *(*(p+i)+j) << ' '; } cout<< endl; int main(int argc, char** argv) { int arr[3][3] = {1,2,3,6,4,2,38,4,2}; func(arr[0],9); // *arr &arr[0][0] arr[0] // 這裡func(arr,9) 形參是int *p 就報錯 p是一個列指針,二維數組不一樣 print_arr(arr); return 0;
案例使用二維數組傳參
float average_score(int *a,int n) { float sum = 0.0; for(int i = 0;i < n; i++) { sum += *(a+i); } return sum/n; } void find_num(int(*p)[3],int num) { for(int i = 0;i < 3 ;i++) printf("%d ",*(*(p+num) + i)); cout << endl; return ; } int main(int argc, char** argv) { int arr[3][3] = {1,2,3,6,4,2,38,4,2}; float ave = 0.0; ave = average_score(*arr,9); printf("%f \n",ave); find_num(arr,0); return 0; }
函數與指針關系的詳細剖析
指針函數
返回值 * 函數名(參數)
#if 0 void find_num(int(*p)[3],int num) { for(int i = 0;i < 3 ;i++) printf("%d ",*(*(p+num) + i)); cout << endl; return ; } #else int * find_num(int(*p)[3],int num) return *(p+num); #endif int main(int argc, char** argv) { int arr[3][3] = {1,2,3,6,4,2,38,4,2}; float ave = 0.0; ave = average_score(*arr,9); printf("%f \n",ave); int * res; res = find_num(arr,0); if(res != NULL) { for(int i = 0;i < 3;i++) printf("%d ",res[i]); cout <<endl; } else printf("can not find\n"); return 0;
函數指針
#include <iostream> using namespace std; int add(int a,int b) { return a+b; } int sub(int a,int b) { return a-b; } int main(int argc, char** argv) { int a = 2, b = 3; int (*p)(int,int); int (*q)(int,int); int ret; p = add; q = sub; printf("%d \n",p(a,b)); printf("%d \n",q(a,b)); return 0; }
回調函數
函數指針數組
類型 (*數組名[下標])(形參);
#include <iostream> using namespace std; int add(int a,int b) { return a+b; } int sub(int a,int b) { return a-b; } int main(int argc, char** argv) { int a = 2, b = 3; int (*funcp[2])(int,int); int ret; funcp[0] = add; funcp[1] = sub; for(int i = 0;i < 2; i++) { ret = funcp[i](a,b); printf("%d \n",ret); } return 0; }
指向指針函數的函數指針數組
數組存放指針,指針指向函數,函數返回值是指針類型。
結構體
- 產生的意義
- 類型描述
- 嵌套定義
- 定義變量、初始化及引用
- 占用內存大小
定義和使用:
#include <iostream> using namespace std; #define NAMESIZE 100 struct simp_st { int i,j; float f; char ch; }; struct birthday_st int year,month,day; struct student_st int id; char name[NAMESIZE]; struct birthday_st birthday; int math; int chinese; int main(int argc, char** argv) struct student_st stu = {10011,"Alan",{3011,22,11},22,54}; struct student_st *p = &stu; printf("%d %s %d-%d-%d %d %d \n",stu.id,stu.name,stu.birthday.year,stu.birthday.month,stu.birthday.day,stu.math,stu.chinese); printf("%d %s %d-%d-%d %d %d \n",p->id,p->name,p->birthday.year,p->birthday.month,p->birthday.day,p->math,p->chinese); struct student_st stu[2] = {{10011,"Alan",{3011,22,11},22,54},{10012,"salay",{2021,2,12},88,66}}; struct student_st *p = &stu[0];// &stu[0] stu for(int i = 0;i < 2;i++,p++) { printf("%d %s %d-%d-%d %d %d \n",p->id,p->name,p->birthday.year,p->birthday.month,p->birthday.day,p->math,p->chinese); } return 0; }
內存對齊問題
addr/sizeof()
構造類型-結構體內存問題及函數傳參
為後面linux高級鋪墊。
- 可以實現一個學生管理系統。
- 產生及意義
- 類型描述
- 嵌套定義
- 定義變量
- 占用內存大小
- 函數傳參
- 位域
union 名{ 數據類型 成員名1; 數據類型 成員名2; };
枚舉類型
enum 名{ 成員1; 成員2; 成員3; }
到此這篇關於C/C++指針、函數、結構體、共用體的文章就介紹到這瞭,更多相關C++指針 函數 結構體 共用體內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!