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

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