int month_lengths[] = {’31’,’29’,’31’,’30’,’31’,’30’,’31’,’31’,’30’,’31’,’30’,’31’,}
因为在分行的情况下,编译程序是通过逗号作为标志的,所以这是合法的。
以上结构可以写为如下的形式:
int month_lengths[] = {’31’,’29’,’31’,’30’,’31’,’30’,’31’,’31’,’30’,’31’,’30’,’31’,}
还有一点必须注意了,字符和字符串的表达式不一样的。单引号用于字符表达式,而双引号则用于字符串表达式的。这是好多人,包括C的老手,最爱犯的错误。写一个换行语句是会
写成 :
printf(’\n’),而在字符判断 *** 作的时候却写成了:
int c
[...]
if((c = getchar()) != "\n"){
do something here
}
[...]
这种低级的错误是很容易避免的,但是一不小心就出错了,而且还不少呢,在教科书、参考书、以及一些文献以及网络文字里经常出现,只要你细心一点就可以发现。这看似问题不大,但是
如果在嵌入式系统,尤其是实时系统有可能造成系统崩溃的,所以写程序时不要报以任何的侥幸心理,必须审慎每一个细节。程序设计不是一门技术,而是一门艺术。
下面看看指针吧。
指针是(pointer)是存放内存地址的变量。 从这个定义中我们可以实力一个这样的概念: 与指针 *** 作相关的最直接的要素是地址,内存地址。这里的地址指内存中另一个变量的位置。
如果一个变量含有一个变量的地址,则称一个变量指向第二个变量。
准备存放指针的变量必须在使用前声明好。 指针的声明由一个基类(base type)、一个星号(*)和变量名组成。 一般的形式为:
type * name
其中,type是指针的基类类型,可以是任何有效的数据类型,name是指针变量的名称。当然了 type *name 和 type * name是等效的,一般的编译器都会在编译程序的时候忽略中间的空格。
指针的基类定义了指针可以指向的变量的类型。 技术上,任何指针类型都可以指向内存的任何位置。然而,指针的 *** 作是基于指针的类型的,也就是说指针变量和其指向的地址的变量的类型必须兼容。即如下的 *** 作时错误的:
int *p
char ch = ’A’
p = &ch
因为类型不匹配,所以这是错误的。其实,这句话不完全对。这只是一个标准罢了,具体还需要看你的编译器的实现了。上面这种方式的 *** 作在好多编译器上是可以通过的,比如,Win-TC、LCC等(在Win-TC下直接通过,而在LCC下也只有一个警告罢了)。 不过采用这种方式设计的程序的可移植性一定是很糟糕的。还有如果在 *** 作中如果你想把指针地址存给一个数组元素时,如果类型不匹配,那么你只有强制转换指针地址的数据类型了,直接赋值是不可能的。所以我们提倡还是采用标准的规定来进行 *** 作。还有下面这一种 *** 作也是错误的,虽然类型是匹配的:
int *p
int i
p = &i
因为i仅被用户声明了,但是没有分配内存,所以这是错误的。一个变量只有在被初始化的时候,才有可能分配到内存的(大多数情况是初始化之后,就分配到内存,但是如果在内存不足的情况就不可能满足这个要求了)。 在指针声明中还存在一个误区,那就是错误的认为在如是的表达式 int *p,m,n中声明了3个指针变量,其实只有第一个(p)是指针变量,而其他两个(m,n)只是int型变量罢了。只有这样才能同时声明几个指针变量的: int *p, *m, *n, ...
指针也可以像一般变量一样进行初始化的,但是你不能给一个一个指针直接的赋值哦。 比如:
int *p
p = 10只是错误的。不过你可以把指针赋值为空,即
int *p = 0或者
int *p
p = NULL
因为在许多的C语言的头文件,如,定义了宏NULL,它是一个空指针常量,所以我们的表达式是合法的,效果和上面的一个相同。
我们可以把一个数组变量赋予一个指针,因为它们都是一种地址的映射罢了。这才是我们的主题。比如:
char str[100], *pointer
pointer = str
这里,pointer指向数组str的首元素,与str[0]或者访问变量str的实质是一样的, *** 作的都是数组的第1个元素,0位置上的元素。如果要访问str数组的第10个元素,那么 *** 作如下:
str[9]或*(pointer + 9) 这是等效的。在指针中也有++,--这样的 *** 作,尤其在指针和数组互 *** 作时,用到的机率最大,因为 *** 作很灵活。比如:
#include
int main(){
char hello[] = "Hello, world !"
char *p
p = hello
do{
printf("%c", *p)
p++
} while(*p)
printf("\n")
return
}
这是一个典型的例子,即用了指针的“自增” *** 作,还是数组合指针互 *** 作的好例子。你的 *** 作还可以是:
p = &hello[3]
*p = hello[3]
*&hello[3] = *p
printf("%d\n",*&hello[3])
hello[3] = *p
printf("%d\n",&hello[3])
hello[3] = *p
printf("%d\n",hello[3])
等等,其中 *&hello[3] 和 &hello[3]的值是一样的,都是读取hello数组中3号元素(第四个元素)的地址的。而语句 p = &hello[3]是把3号元素的地址赋给指针变量,而hello[3] = *p
是把指针p的值赋给hello[3]的。这也是互 *** 作的一种方式。
注意了: *++P , ++*p 和 *p++ 以及 *--p , --*p 和 *p-- 表示的结果是不同的。因为++、--的优先级高于*的优先级,所以前边的表达式相当于 *(++p) , *(++p) 和 *(p++) 以及 *(--p) , *(--p) 和 *(p--)。建议牢牢的记住 *** 作符的优先级,因为在这些细节上稍不注意就会产生问题,我们意想不到的。
数组和指针都可以当作参数来处理,但是才用指针的概率要高一些,因为指针较数组更加灵活。例如,你可以如下传递一个数组或指针变量:
#include
int main(){
char hello[] = "Hello, world !\n"
char *p
p = hello
printf(hello)
printf(p)
printf("%s", p)
printf("%s", hello)
do{
printf("%c", *p)
p++
} while(*p)
printf("\n")
return
}
在LCC中是完全通过的,其输出结果是:
Hello, world !
Hello, world !
Hello, world !
Hello, world !
Hello, world !
但是在有些编译器上,语句:
printf(hello)
printf(p)
可能只会输出字符串的第1个元素,因为有些编译器采取的是对字符串进行“截取”的方式来处理,所以其结果有可能是:
HHHello, world !
Hello, world !
Hello, world !
定义为空指针,在后面程序中可以将这个空指针指向其他地址变量。
如果一个变量声明时在前面使用 * 号,表明这是个指针型变量。指针不仅可以是变量的地址,还可以是数组、数组元素、函数的地址。通过指针作为形式参数可以在函数的调用过程得到一个以上的返回值,不同于return(z)这样的仅能得到一个返回。
指针是一把双刃剑,许多 *** 作可以通过指针自然的表达,但是不正确的或者过分的使用指针又会给程序带来大量潜在的错误。
扩展资料:C 语言的运算范围的大小直接决定了其优劣性,C 语言中包含了34种运算符,因此运算范围要超出许多其它语言,此外其运算结果的表达形式也十分丰富。
此外,C 语言包含了字符型、指针型等多种数据结构形式,因此,更为庞大的数据结构运算它也可以应付。
9 类控制语句和32个KEYWORDS是C语言所具有的基础特性,使得其在计算机应用程序编写中具有广泛的适用性,不仅可以适用广大编程人员的 *** 作,提高其工作效率,同 时还能够支持高级编程,避免了语言切换的繁琐。
FILE *fp 这就是文件指针定义方式啊 还问 文件指针怎么定义?你是想知道FILE是什么吧?
它是一个结构体:
struct _iobuf {
char *_ptr
int _cnt
char *_base
int _flag
int _file
int _charbuf
int _bufsiz
char *_tmpfname
}
typedef struct _iobuf FILE
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)