6.1 内存和地址
1. 内存中的每个位置由一个独一无二的地址标识
2. 内存中的每个位置都包含一个值。
6.2 值和类型
我们不能通过检查一个值的位来判断它的类型。我们要看这个值如何被解释。
6.3 指针变量的内容
int a = 1;
int b = 2;
int *c = &a;
int *d = &b;
则c存储的是a的地址,d存储的是b的地址。
变量的值就是分配给该变量的内存位置所存储的数值。
6.6 NULL指针
NULL作为一个特殊的指针变量,表示不指向任何东西。要使一个指针变量为NULL,给它赋值0即可。
备注:
int a = 2;
int *b = &a;
中,指针变量指的是b,而不是*b,这点非常重要。
6.9 指针常量
假定变量a存储于位置100,则
*100 = 25;
的意思是把25赋值给a吗?实际上这条语句是非法的,因为字面值100的类型是整型,而间接访问操作只能作用于指针类型表达式。如果确定要把25存储于位置100,我们必须进行强制类型转换:
*(int *)100 = 25;
6.10 指针的指针
int a = 12;
int *b = &a;
int **c = &b;
c的类型是:指向整型的指针的指针。
6.12 实例
1. 字符串长度
#include <stdlib.h>
size_t strlen(char *string)
{
int length = 0;
while ( *string++ != '\0' ){
length += 1;
}
return length;
}
2. 在字符串指针数组中进行单一字符的查找:
#include <stdio.h>
int find_char( char **strings, char value ){
char *string = NULL;
while ( ( string = *strings++ ) != NULL ){
while ( *string != '\0' ){
if ( *string++ == value ){
return 1;
}
}
}
return 0;
}
int main(void)
{
char *string1 = "hello";
char *string2 = "world";
char *string3 = "python";
char *str[3] = {string1, string2, string3};
char **strings = str;
if (find_char(strings, 't')){
printf("find it\n");
}
else{
printf("not find it\n");
}
return 0;
}
3. 字符串查找的第二版本:
#include <stdio.h>
#include <assert.h>
int find_char( char **strings, char value ){
assert( strings != NULL );
while ( *strings != NULL ){
while ( **strings != '\0' ){
if ( *( *strings )++ == value){
return 1;
}
}
strings++;
}
return 0;
}
int main(void)
{
char *string1 = "hello";
char *string2 = "world";
char *string3 = "python";
char *str[3] = {string1, string2, string3};
char **strings = str;
if (find_char(strings, 't')){
printf("find it\n");
}
else{
printf("not find it\n");
}
return 0;
}
6.13 指针运算
例子:清除一个数组中的所有元素
1. 正向
#define N_VALUES 5
float values[N_VALUES];
float *vp = NULL;
for ( vp = &values[0]; vp < &values[N_VALUES]; ){
*vp++ = 0;
}
2. 反向
#define N_VALUES 5
float values[N_VALUES];
float *vp = NULL;
for ( vp = &values[N_VALUES]; vp > &values[0]; ){
*--vp = 0;
}
3. 有点错误的:
#define N_VALUES 5
float values[N_VALUES];
float *vp = NULL;
for ( vp = &values[N_VALUES - 1]; vp >= &values[0]; vp-- ){
*vp = 0;
}
因为:标准允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针进行比较,但不允许与指向数组第一个元素之前的那个内存位置的指针进行比较。
习题:
1.
#include <stdio.h>
char *find_char( char const *source, char const *chars){
char *temp = NULL;
while ( *chars++ != '\0' ){
temp = source;
while ( *source++ != '\0' ){
if ( *chars == *source ){
return source;
}
}
source = temp;
}
return NULL;
}
int main(void)
{
char *source = "abcdef";
char *chars = "xrcqef";
printf("%s\n", find_char( source, chars ));
return 0;
}
程序输出:
2.
#include <stdio.h>
int del_substr( char *str, char const *substr ){
char *temp = NULL;
while ( *str != NULL){
while ( *str != *substr){
str++;
}
temp = str;
while ( ( *str != NULL ) && ( *str == *substr ) ){ //不要写 ( *str++ == *substr++ ),这样会导致'\0'也被判断过
str++;
substr++;
}
if ( NULL == *substr ){
while ( *temp++ = *str++ ){
;
}
*temp = '\0';
return 1;
}
}
return 0;
}
int main(void)
{
char str[8] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', '\0'};
char substr[4] = {'c', 'd', 'e', '\0'};
if ( del_substr( str, substr ) ){
printf("%s\n", str);
}
return 0;
}
程序输出:
3. 不知道如何反转字符串,在用指针的情况下。看了下答案后,发现自己把问题想复杂了:
#include <stdio.h>
void reverse_string( char *str )
{
char *last_char;
for ( last_char = str; *last_char != '\0'; last_char++ ){
;
}
last_char--;
while ( str < last_char ){
char temp;
temp = *str;
*str++ = *last_char;
*last_char-- = temp;
}
}
int main(void)
{
char str[6] = {'h', 'e', 'l', 'l', 'o', '\0'};
reverse_string(str);
printf("%s\n", str);
return 0;
}
城西输出:
4.
#include <stdio.h>
#include <stdlib.h>
#define MAXLINE 1000
int main(void)
{
int arr[MAXLINE];
int i = 0;
int j = 0;
for ( i = 0; i < MAXLINE; i++ ){
if ( !( i % 2 ) && ( 2 != i ) || ( i == 1 ) ){
arr[i] = 0;
}
else{
arr[i] = 1;
}
}
for ( i = 3; i < MAXLINE / 2; i++ ){
if ( !arr[i] ){
continue;
}
for ( j = 2 * i; j < MAXLINE; j += i ){
arr[j] = 0;
}
}
for ( i = 0; i < MAXLINE; i++ ){
if ( arr[i] ){
printf("%d ", i);
}
}
return 0;
}
程序输出:
6.
#include <stdio.h>
#include <stdlib.h>
int primeNumCount(int arr[], int len){
int count = 0;
int i = 0;
int j = 0;
for ( i = 0; i < len; i++ ){
if ( !( i % 2 ) && ( 2 != i ) || ( i == 1 ) ){
arr[i] = 0;
}
else{
arr[i] = 1;
}
}
for ( i = 3; i < len / 2; i++ ){
if ( !arr[i] ){
continue;
}
for ( j = 2 * i; j < len; j += i ){
arr[j] = 0;
}
}
for ( i = 0; i < len; i++ ){
if ( arr[i] ){
count++;
}
}
return count;
}
int main(void)
{
int arr[100000];
int i = 0;
int preCount = 0;
int curCount = 0;
for ( i = 1000; i <= 100000; i += 1000 ){
curCount = primeNumCount( arr, i );
printf("%3d ", curCount - preCount);
preCount = curCount;
if ( !( i % 8000 ) ){
printf("\n");
}
}
return 0;
}
程序输出:
分布挺均匀的。