目录
指针 + 一维整型数组
定义一个一维整型数组:
int a [5]
此时数组名a的类型就是int [5],(去掉标识符,剩下的就是它对应的类型),a的值就是元素的首地址。这是一维字符型数组的性质。
所以在定义时,可以写成以下形式:
int *p = a; //表示p指向了数组a,此时的*仅仅代表p是一个指针变量
int *p = &a[0]; //因为数组名a的值就是数组首元素的地址,即 a <=> &a[0]
所以*p <=> a[0] //此时的*是指针运算
那么我们如何用指针的方式从数组里取出元素呢?在此之前,需要理解指针的运算。
& //取地址
* //指针运算符,也叫解引用p+1 //加n 表示 跳过了n个基类型 ,p是指针类型的变量
p-1
p++
p--
指针比较 > >= < <= == !=p - q //表示差了多少元素(基类型)
//必须是同一类型的指针注意:指针不能做加法。
所以访问数组元素:
int a[5];
int *p = a;
p[i] <=> *(p+i) <=> a[i] <=> *(a+i) <=> *p++
a[i] 的本质是个表达式,a和i相当于是运算数,a[i] 等价于 *(a+i)
以下是简单示例,打印一个数组
int a[5];
int *p = a;
int i = 0;
for (i = 0; i < len; ++i)
{
printf("%d ",*(a+i));
}
putchar('\n');
数组作为函数参数:
形参 -- ①数组形式 //本质上是一个指针类型变量 , int *a
②数组长度,int len
实参 --① 数组名 //数组名代表数组首地址
②数组长度
下面是简单应用:找数组里的最大值,实参应该传入一个数组名和数组长度
int maxOfArray(int *a,int len)
{
int max = *(a+0); //*a
int i = 0;
for (i = 1; i< len; ++i)
{
if (*(a+i) > max)
{
max = *(a+i);
}
}
return max;
}
指针操作一维字符型数组
char s[ ] = "hello";
char *p = s; //与一维整型数组相同
const关键字
const int a //const表示只读,此时a是一个只读的变量
const 的位置不同,限定的范围也不同,以下有四种写法:
①const int *p //const此时限定的是基类型,表示不能通过*p的方式,修改基类型数据。
②int const *p //与①等价
③int * const p //const限定的是指针变量,表示将p限定为只读,p不能修改
④const int * const p // 限定了基类型和指针变量
总结:
在函数传参时,形参设计为const char *,目的是防止函数中的误操作。
好处:(1).提前发现问题,将运行时问题,提前到编译时 。
(2).const char *做形参,实参还可以是数组名,指针变量 char *p //const char *p ,可以直接是一个字符串常量 提高参数的适用性。
指针 + 字符串
在c语言中是按照字符数组的形式存储,字符串常量 --- 存储在字符串常量区 。
eg :char s[ ] = "hello"; //表示 在栈上开辟一块空间,用字符串常量中的 "hello"进行初始化。
因此有两种方式可以处理字符串
方式1:
const char *p = "hello";
*p = ‘H’ //这是错误示例
表示 p指向了 字符串常量区中的 "hello",因为 是指向了字符串常量区 ,只能做读取操作,不能修改,虽然可以运行,但是会出现段错误。
方式2:
char s[ ] = "hello";
char *p = s;
*p = 'H'; //此时可以修改
这是因为此时操作的是栈上的空间,可以修改。
总结:在操作字符串常量区的字符串时,只读不修改,可以写成:
const char *p = "hello"; //不小心修改时,在编译时可以报错提醒。
补充:
1.快速排序
以下面的图片说明
代码实现:
void swap(int *a,int *b)
{
int t = *a;
*a = *b;
*b = t;
}
void quickSort(int *begin,int *end)
{
int *p = begin;
int *q = end;
int *k = begin; //
if (begin >= end)
{
return ;
}
while (begin < end)
{
while (begin < end && *end >= *k)
{
--end;
}
while (begin < end && *begin <= *k)
{
++begin;
}
swap(begin,end);
}
swap(k,begin);
quickSort(p,end-1);
quickSort(begin+1,q);
}
2.实现字符串相关函数
(1)gets
char * Gets(char *s)
{
char *ret = s;
while ((*s = getchar())!='\n')
{
++s;
}
*s = '\0';
return ret;
}
(2)puts
int Puts(const char *s)
{
if (s == NULL)
{
return -1;
}
while (*s != '\0')
{
putchar(*s++);
}
putchar('\n');
return 0;
}
(3) strlen
size_t Strlen(const char *s)
{
const char *ret = s;
while (*s!='\0')
++s;
return s-ret;
}
(4)strcpy /strncpy
char * Strcpy(char *dest,const char *src)
{
char *ret = dest;
while (*src != '\0')
{
*dest = *src;
++dest;
++src;
}
*dest = '\0';
return ret;
}
-------------------------------------------------------------------
char * Strncpy(char *dest,const char *src,size_t n)
{
char *ret = dest;
while ( n!=0 &&*src != '\0')
{
*dest = *src;
++dest;
++src;
--n;
}
while(n)
{
*dest = '\0';
++dest;
--n;
}
return ret;
}
补充:返回值是char *,为了能进行链式操作
(5)strcat /strncat
char * Strcat(char *dest,const char *src)
{
char *ret = dest;
while (*dest != '\0')
++dest;
while (*src != '\0')
{
*dest = *src;
++dest;
++src;
}
*dest = '\0';
return ret;
}
-----------------------------------------------------------
char * Strncat(char *dest,const char *src,int n)
{
char *ret = dest;
while (*dest != '\0')
++dest;
while ( n && *src != '\0')
{
*dest = *src;
++dest;
++src;
--n;
}
*dest = '\0';
return ret;
}
(6)strcmp /strncmp
int Strcmp(const char *s1,const char *s2)
{
while (*s1==*s2 && *s1!='\0' && *s2!='\0')
{
++s1;
++s2;
}
return *s1 - *s2;
}
-------------------------------------------------------------
int Strncmp(const char *s1,const char *s2,size_t n)
{
//n = 3 s1 s2
//n = 2 s1+1 s2+1
//n = 1 s1+2 s2+2
// s1+3 s2+3 //n = 0
while ( n > 1&&*s1==*s2 && *s1!='\0' && *s2!='\0')
{
++s1;
++s2;
--n;
}
return *s1 - *s2;
}
(7)补充:memcpy
void *memcpy(void *dest, const void *src, size_t n)
{
//一个字节一个字节拷贝
}
void * //NULL 空指针
//空类型的指针 --- 万能指针
//可以接收任意类型的指针
注意:
1.注意:如果用 空类型指针 进行 间接运算,必须 转换成 有明确类型的指针。
以下是简单示例:
#include <stdio.h>
#include <string.h>
#include <assert.h>
void Memcpy(void *dest,const void *src,int n) //可以拷贝任意类型的数组
{
assert(dest != NULL);
char *p = dest;
const char *q = src;
while (n)
{
*p = *q;
p++;
q++;
--n;
}
}
int main(void)
{
int a[5] = {1,2,3,4,5};
int b[5];
Memcpy(NULL,a,5*sizeof(a[0]));
int i = 0;
for (i = 0; i < 5; ++i)
{
printf("%d\n",b[i]);
}
return 0;
}