C語言基礎學習(五)

注:關於數組名的一個通常兩個例外
char arr[10];
1: arr 通常情況表示首元素的地址
2: &arr 表示整個數組的地址
sizeof(arr) 整個數組佔用內存空間大小

基地址 變量的地址值

地址包括兩個方面的內容
一個叫對象大小 一個是基地址(32位或者64位)

指針:
用來存儲地址的變量 指針變量簡稱指針
變量就要有類型, 指針變量是類型帶*
int a; 定義一個int類型的變量a
char b; 定義一個char類型的變量b

int * a ; 定義一個int指針類型的變量a
char * b; 定義一個char指針類型的變量b
32位機 32根地址線 每個地址值都是由32位組成 4B
一個地址只能放一個字節

指針類型是表示該地址對應的對象是什麼數據類型
指針變量的值是某個基地址

指針定義 *表示是個指針類型變量
一級指針
數據類型 *  變量名
二級指針
變量中存的是一個一級指針變量的地址
數據類型 **  變量名

int * q;
char *p;
float * x;

void * qt ; 注意沒有void a 這種寫法,因爲void沒有大小
qt定義爲一個通用指針,只有基地址沒有對象大小
一般只做傳參, 但是在使用之前必須先強制類型轉換成已知類型

指針的初始化和賦值
int a;
int * q = &a; // 直接使用變量a的地址給指針變量q賦值
等同於 int * q ;
q = &a;
在賦值過程中不能直接使用常量給一個指針賦值
int *q = 0xbfffc000;不允許,因爲內存分配是系統決定,運行時候不知道準確的地址值
int *q = NULL ; NULL是唯一一個可以給指針賦值的常量

給一個指針變量賦值,要求打印該指針變量的值,和該指針變量所在的地址
%p

指針的解引用
int a = 100;
int *q = &a;
q ==== &a;
*q 是通過q的值來得到對應地址中存的值
也就是通過&a來得到對應地址中的值, 也就是a的值
*q = 100; 把100放進指針變量q對應的地址中

有兩int類型變量a, b
通過兩個指針把a 和b值進行交換

int a = 100;
int b = 200;
int *p = &a , *q = &b ; 等價於int *p ; int *q;
int temp;
temp = *p; //100
*p = q ; // a的值更改q 也就是200
*q = temp ;// 100

%d %d a , b
%d %d *p , *q

指針的運算(以對象爲單位)

q + 1
q ++ q 值會變
q - 2
q –
q - p q和p 是同類型指針,實際得到的是相隔對象的個數

指針和數組的關係
int arr[5];
arr[ 1 ]==> *( arr + 1) ==> *( &arr[0] + 1) ==> *(&arr[1])

p[-1] ==> *( p -1 ) ==> -1 [ p ]

如果 int arr[5]= {12, 4,5, 7,8,};
int * p = arr; // *p ==== arr NG這個是錯誤的理解 p ==== arr 對
max = *p; // arr[0] *arr
for(i=1 ; i<5 ; i++)
{
if(max < *(p+i)) // arr[0+i] *(arr+i)
{
max = *(p+i);
}
}
1: 如果定義了一個數組int arr[5], 並設置了指針等於數組名 int *p = arr
那麼在操作的時候 p 和arr是可以混用的
arr[i] p[i]
*(p+i) *(arr+i)

2: 使用字符串直接給指針賦值 和 使用字符數組名給指針賦值 有差異
char str[10] = “hello”;

char *p = str;// 用數組str的首元素地址給p賦值
char *q = “hello”;// 使用只讀數據段中的"hello"的首元素地址給取q賦值

可以通過*p 修改字符數組的值,
但是不能通過 *q修改只讀數據段的值,該值是在編譯時候就已經確定的

3: 指針賦值
int *q = NULL;
q = 100 有風險, 訪問地址100涉嫌訪問非法空間
指針解引用後賦值
q 在q操作之前要先判斷q的值不爲NULL
if(q !=NULL)
*q = 100;

4; 數組名在傳參的時候,實際傳的是首元素地址
函數的形參應該爲同類型的指針變量
如果在函數中需要知道該數組的元素個數, 則需要再傳一個參數告訴函數

函數的定義 聲明 和調用
定義
函數的返回值類型 函數名(函數的形參)
{
函數的實現
}

定義一個函數, 傳入的參數是兩個int類型變量a b , 返回值是int
int func ( int a, int b)
{
}

定義一個函數, 傳入的參數是一個int類型變量a 一個字符指針變量 , 沒有返回值
void func (int a , char * p)
{
}

定義一個函數, 沒有傳入參數, 返回值是個char
char func (void )
{

}

函數的聲明
函數的返回值類型 函數名(函數的形參);

函數的調用

在main函數中調用一個函數, 可以返回兩數中比較大的值

例子:
定義一個函數, 要求可以返回兩個int類型數據之和

定義一個函數, 已知傳入數組有10個元素,要求計算該數組各個元素之和
1: 如果不知道數組的元素個數
2: 爲什麼“數組類型不匹配也可以”
#include <stdio.h>
//int sum ( int a[10])// 在形參中定義的數組int a[10]等同與int *a
//int sum ( int a[])// 在形參中定義的數組int a[10]等同與int *a
//int sum ( int *a, int length)// 在形參中定義的數組int a[10]等同與int *a,
// int *a = &arr[0] ; int length = 11;
int sum( int a[11] , int length)// 在形參中定義的數組名實際只是一個指針變量
{
printf(" sizeof(a) = %d \n", sizeof(a)); 實際查看的是一個指針變量的大小, 32位
int i;
int sum = 0;
for(i=0 ; i<length; i++)
sum += a[i];
return sum ;
}

int main(void)
{
int arr[ ] = {9,8,7,5,6,7,8,4,6,2, 11}; // 非形參
sizeof(arr) 表示整個數組的大小,44B ; 例外情況之一
int result = sum( arr , sizeof(arr)/sizeof(arr[0]) );表示一個元素所佔用的空間,int類型元素,4B
printf(“result = %d \n”, result);

}

strtoull

輸入AABB , 16 返回數值 43707
1010 , 8 返回數值 520

1 9 a b c d e f …

, 16
  1. ptr == NULL
  2. digit = *ptr - ‘0’;
  3. digit = *ptr - ‘A’ + 10
  4. digit = *ptr - ‘a’ + 10
  5. ret *= base;

1Aa 16
digit = 1; ret = 016 +1
digit = 10; ret = 1
16+10
digit = 10; ret = 26*16 + 10

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章