数组与指针

//使用递归来计算阶乘
#include<stdio.h>
long rfact(int n);
int main()
{
int num;

printf("This program calculate factorials.\n");
printf("Enter a value in the range 0-12(q to quit): \n");
while(scanf("%d",&num)==1)
{
if(num <0 )
printf("No negative number,please.\n");
else if(num > 12)
printf("Keep input under 12.\n");
else
printf("recursion: %d factorial = %ld\n",num,rfact(num));

printf("Enter a value in the range 0-12(q to quit): \n");
}
printf("Bye.\n");
return 0;

}

long rfact(int n)
{
long ans;

if(n > 0)
ans = n * rfact(n-1);
else
ans = 1;

return ans;
}

//以二进制形式输出整数
#include<stdio.h>
void to_binary(unsigned long n);

int main()
{
unsigned long number;
printf("Enter an integer (q to quit): \n");
while(scanf("%lu",&number)==1)
{
printf("Binary equivalent: ");
to_binary(number);
putchar(‘\n‘);
printf("Enter an integer (q to quit): \n");

}
printf("Done.\n");

return 0;
}

void to_binary(unsigned long n)
{
int r;
r = n % 2;
if(n >= 2)
to_binary(n / 2);
putchar(‘0‘ + r);

}

//scanf("%*s");可以跳至下一个空白字符

指针:
/*
指针要说明所指变量的类型,因为有些指针操作需要知道变量类型所占用的存储空间,同时程序也需要知道地址中存储的是何种类型。
大多数系统,指针是由无符号整数表示,但不能把它看作整数类型,是一种新的数据类型,%p作为输出格式。
不能进行相加

编写程序时: 一个变量一般有两种属性:变量名,数值;
编译和加载后:同一个变量在计算机中有两个属性是地址和数值。
*/

函数返回值类型:
函数返回值的类型和声明的类型不相同时,实际返回值会将指定的值转化为声明类型。

在初始化前,和普通变量类似,数组元素的数值是不定的。

小技巧:如果days是数组,那么可以用:sizeof days / sizeof day[0]来计算出数组中元素的数目。

例题:

int a[] = {21,43};这种格式在元素个数有误时,我们可能意识不到

int a[] = {31,43,[1] = 45};后面的指定初始化会覆盖前面的数值,其他没有指定的都为0

不允许的赋值方式:

int a[]={34,34}; 可以
int b[2];

b = a; 不可以
b[2]={2,5};不可以

数组说明:
使用超出数组边界的索引会改变其他变量的数值,程序也许能够运行,但是运行结果会很奇怪

小技巧:在数组声明中使用符号常量,然后程序中需要使用数组大小的地方都直接引用符号常量

数组是顺序存储的

多维数组的初始化 a[][]={{},{},} 与a[][] = {}在数值个数不够时,效果是不同的。

数组名同时也是数组首元素地址

指针说明:
对一个指针加1的结果也是对该指针增加一个存储单元,不是加一个字节

对于包含多个字节的数据类型,对象的地址通常指的是其首字节的地址
指针数值就是它所指向的对象的地址,地址的内部表示方式由硬件来决定

小技巧:
被调用的子函数可以得到数组的地址但它不知道数组中元素的数量,两种选择:1.函数代码中写上固定的数组大小 2.传递一个参数表示数量

声明数组参量:
int sum(int *ar,int n);
int sum(int *,int);
int sum(int ar[],int n);
int sum(int [],int n);

定义时名称是不可以省略的:
int sum(int *ar,int n)
int sum(int ar[],int n)

数组和指针的补充:
C保证在为数组分配存储空间的时候,指向数组之后的第一个位置的指针也是合法的,但对里面的内容不作任何保证

*str++ 由于* ++具有相同的优先级,但结合是从右到左,所以++先作用

ar是一个指针变量时,才可以用ar++,数组名不可以

指针的运算:

求有效差值前提是两个指针指向同一个数组(或其中一个指向数组后面的第一个地址)

减去一个整数是会,移动的存储单元,不是字节

比较两个指针的值的前提是:两个指针具有相同的类型

注意:
不能对未初始化的指针取值
如:int *pt; *pt = 5; 此时不知道5会存储在什么位置,该位置可能对系统产生危害。

系统分配用来存储指针本身的内存地址空间,而不分配用来存储数据的内存空间

const的一些用法:

例子:rates是数组名,const double * pd = rates; *pd =29.89,和pd[2]是不允许的,rates[0] = 99.99是允许的。

将常量和非常量的地址赋给指向常量的指针式合法的

当const放*前面,指向常量,值不可变,位置可变
当const放*后面,指向变量,值可变,位置不可变。

*zippon = zippon[0] = &zippon[0][0]

int (* pz)[2];指向一个包含2个int值的数组 ,[]的优先级是高于*号的

int *pz[2];两个指针组成的数组

指针的赋值不支持类型转化,类型一定要一样

把非const指针赋给const指针是允许的,这样的赋值有一个前提:只进行一层间接运算
如例题:
const int **p2;
int *p1;
const int n = 13;
pp2 =&p1; //假设允许
*pp2 =&n;
*p1 = 10;
//这题中,n的地址给*pp2,于是间接给了p1,然后p1就可以改变n了,所以不成立。

二维数组的参数传递:
假设junk是指向由4个int值构成的数组的指针;
声明可以如下:
1.void somefunction(int (* pt)[4])
2.void somefunction(int pt[][4]);
如果在声明中第一个[]中填入数字也是可以的,但是编译器将忽略掉,合理做法可以加一个参数。

多维数组的声明:
void sum(int (*ar)[34][34][34],int rows);
void sum(int ar[][34][43][43],int rows)

变长数组的(VLA)
1.变长数组的“变”并不表示在创建数组后,可以改变其大小。是指其维数大小可以用变量来指定

例子如下:

声明:int sum(int rows,int cols,int ar[rows][cols]);//ar是一个指向由cols个int组成的数组

C99中可以用:int sum(int,int,int ar[*][*]);

函数定义如下:
int sum(int rows,int cols,int ar[rows][cols])
{
int r;
int c;
int tot = 0;

for(r = 0;r < rows;r++)
for(c = 0;c < cols;c++)
tot += ar[r][c];
return tot;

}

C不支持把整个数组作为函数参数进行传递的

复合文字(一个代码,要支持C99编辑器):
#include<stdio.h>
#define COLS 4
int sum2d(int ar[][COLS],int rows);
int sum(int ar[],int n);
int main()
{
int total1,total2,total3;
int * pt1;
int (*pt2)[COLS];

pt1 = (int [2]){10,20};
pt2 = (int [2][COLS]){{1,2,3,-9},{4,5,6,-8}};

total1 = sum(pt1,2);
total2 = sum2d(pt2,2);
total3 = sum((int []){4,4,4,5,5,5},6);
printf("total1 = %d\n",total1);
printf("total2 = %d\n",total2);
printf("total3 = %d\n",total3);

return 0;
}

int sum(int ar[],int n)
{
int i;
int total = 0;

for(i = 0;i < n;i++)
total += ar[i];

return total;

}

int sum2d(int ar[][COLS],int rows)
{
int r;
int c;
int tot = 0;

for(r = 0;r < rows;r++)
for(c = 0;c < COLS;c++)
tot += ar[r][c];

return tot;
}

时间: 2024-10-22 07:19:25

数组与指针的相关文章

数组与指针的区别?

数组要么在静态存储区被创建(如全局数组),要么在栈上被创建.指针可以随时指向任意类型的内存块.    (1)修改内容上的差别 char a[] = "hello";  //它们有各自的内存空间:a[0] = 'X';char *p = "world"; // 注意p 指向常量字符串p[0] = 'X'; // 编译器不能发现该错误,运行时错误 (2) 用运算符sizeof 可以计算出数组的容量(字节数).sizeof(p),p 为指针得到的是一个 指针变量的字节数,

数组与指针操作

一,数组 1,const int array[5] = {0, 1, 2, 3, 4}; 2,c99新特性,可以对指定的数组的某一个元素初始化.例如:int array[10] = {1, 3, [4] = 2, 6, 7, [1] = 32};如果多次对一个元素进行初始化,取最后一次的值. 3,c不支持把数组作为一个整体来赋值,也不支持用花括号括起来的列表形式进行赋值. 4,sizeof表达式被认为是一个整数常量. 5 * 5 - 1 就是整数常量表达式. 5,变长数组int array[n]

(C/C++)区别:数组与指针,指针与引用

1.数组跟指针的区别 数组要么在静态存储区被创建(如全局数组),要么在栈上被创建.数组名对应着(而不是指向)一块内存,其地址与容量在生命期内保持不变,只有数组的内容可以改变. 指针可以随时指向任意类型的内存块,它的特征是“可变”,所以我们常用指针来操作动态内存.指针远比数组灵活,但也更危险. 数组和指针特点的简单比较: 数组 指针 保存数据 保存地址 直接访问数据 间接访问数据,先取得指针的内容,然后以它为地址取得数据 用于存储数目固定且类型相同的数据 通常用于动态数据结构 编译器自动分配和删除

C语言关于数组与指针内容小结

数组的基本概念 什么是数组:数组就是:数组是相同类型的元素的一个集合       类型说明符 数组名 [常量表达式]: 其中,类型说明符是任一种基本数据类型或构造数据类型.数组名是用户定义的数组标识符.方括号中的常量表达式表示数据元素的个数,也称为数组的长度.例如: int a[10]; /* 说明整型数组a,有10个元素 */ float b[10], c[20]; /* 说明实型数组b,有10个元素,实型数组c,有20个元素 */ char ch[20]; /* 说明字符数组ch,有20个元

编程练习之数组与指针

数组与指针 阅读如下代码,为何出错. 1 int main() { 2 char a[] = { "I am a bad boy" }; 3 char * pA = new char[ sizeof( a ) ]; 4 pA = a; 5 6 for ( size_t i = 0; i < sizeof( a ); ++i ) { 7 std::cout << *pA << std::endl; 8 ++pA; 9 } 10 delete [] pA; 1

数组与指针的本质

指针是C/C++语言的特色,而数组名与指针有太多的相似,甚至很多时候,数组名可以作为指针使用.于是乎,很多程序设计者就被搞糊涂了.而许多的大学老师,他们在C语言的教学过程中也错误得给学生讲解:"数组名就是指针".很幸运,我的大学老师就是其中之一.时至今日,我日复一日地进行着C/C++项目的开发,而身边还一直充满这样的程序员,他们保留着"数组名就是指针"的误解. 想必这种误解的根源在于国内某著名的C程序设计教程.如果这篇文章能够纠正许多中国程序员对数组名和指针的误解,

【好程序员笔记分享】——数组与指针

ios培训 ------我的c语言笔记,期待与您交流! 前面我们介绍了关于C语言的内存分配问题,下面我们就开始介绍关于C语言的两个非常重要的知识点:数组与指针 数组与指针其实不仅仅是再C语言中,再OC中(当然OC是内部已经帮我们处理好了,但是还有存在大量的指针),C#中,C++中等待一些开发中都是非常常见的,所以作为一个程序员是必须掌握的. 一.数组:相同类型的集合 1:一维数组 平时我们都是申明一个变量,那么如果变量很多我们要怎么做呢,这个时候我们就能用到数组,那么什么是数组呢? 首先来看一个

深入理解 [指针函数] 、[函数指针]、[指针的指针]、[指向指针数组的指针]

指针函数 1.指针函数是指带指针的函数,即本质是一个函数.当一个函数声明其返回值为一个指针时,实际上就是返回一个地址给调用函数,以用于需要指针或地址的表达式中. 函数返回类型是某一类型的指针: 格式: 类型标识符  *函数名(参数表) int *match(void *key_x,void *key_y); 解析:首先来说它是一个函数,只不过这个函数的返回值是一个地址值.函数返回值必须用同类型的指针变量来接受,也就是说,指针函数一定有函数返回值,而且,在主调函数中,函数返回值必须赋给同类型的指针

把《c++ primer》读薄(4-2 c和c++的数组 和 指针初探)

督促读书,总结精华,提炼笔记,抛砖引玉,有不合适的地方,欢迎留言指正. 问题1.我们知道,将一个数组赋给另一个数组,就是将一个数组的元素逐个赋值给另一数组的对应元素,相应的,将一个vector 赋给另一个vector,也是将一个vector 的元素逐个赋值给另一vector 的对应元素: //将一个vector 赋值给另一vector,使用迭代器访问vector 中的元素 vector<int> ivec(10, 20); vector<int> ivec1; for (vecto