指標,c入門
注意:int pointer不是取值操作符,只是一個宣告指標的操作符號
下邊pointer才是取值操作符
指標變數是變數,指標是地址
*號表示從p的記憶體單元中所指的地址中讀取內容
定義格式:型別識別符號 *指標變數名
說明
1)號用於定義指標變數,但指標變數名不包括號
2)一個指標變數只能指向同一型別的變數
3)指標變數本身是整型的,指標變數本身也有自己的地址,佔四個位元組
取地址運算:用&變數名可以取得該變數的實體地址取內容運算:用*指標表示式取得指標變數記憶體單元儲存中存的另一個記憶體地址裡的值給指標變數賦值
1)指標變數使用前必須要有值
2)指標變數的數值必須是地址值,不能直接用一個整型賦值
3)定義格式:int a, *p =&a;或int a,*p; p=&a; 4)可以給指標賦空值,此時指標不指向任何變數:p=NULL;
*只是表示它是指標
這裡需要和陣列一起理解。 C中的陣列實際上定義的是一個指標為首元素地址向後依次移動元素資料大小的位元組,取得該元素的地址所以必須規定指標所指資料型別,從而保證對資料訪問的完備性
#include <stdio.h>
void exchange(int *q1,int *q2,int *q3)//int *q1=p1
{
void swap(int *pt1,int *pt2);//如果a<b<c
//去呼叫函式 ,用於交換&……&%
if(*q1<*q2)
{
swap(q1,q2);
}
if(*q1<*q3)
{
swap(q1,q3);
}
if(*q2<*q3)
{
swap(q2,q3);
}
}
void swap(int *pt1,int *pt2)
{
int pt;
if(*pt1<*pt2){
pt=*pt1;
*pt1=*pt2;
*pt2=pt;//記得加*號只有在取地址和定義函式裡邊的時候不用加星號
}
}
int main()
{
void exchange(int *q1,int *q2,int *q3);//使得a>b>c
int a,b,c,*p1,*p2,*p3;
scanf("%d,%d,%d",&a,&b,&c);
p1=&a;
p2=&b;
p3=&c;
exchange(p1,p2,p3);
printf("%d>%d>%d",a,b,c);
return 0;
}
取p=&a【3】,即為取了第三個陣列
我去試了下,p++是a的地址+4,不知道就動手 哈~
整型地址加了4,就相當於陣列的下一個元素了
+i表示指向第i個元素
p=a等價於p=&a【0】
指標本質也是個變數,在自己的實體地址裡存的是別人的實體地址 實體地址是個數字,所以可以對指標進行算數運算
/*a+10是指向a[10];的
p<(a+10)就是p的地址通過p+=1;依次往後加,但要小於a[10]的地址
實際上for(p=a ; p<(a+10) ; p+=1) 就相當於
for( i=0; i<10; i++ )
printf("%d ", a[i] );
現在相當於是將指標p指向a[0],然後p指向的地址依次變成a[1]……a[9];*/
//p=a等價於p=&a【0】 陣列名存放的就是首元素的實體地址
//a+10是地址範圍
//將*p指向陣列的首地址 ,此處將p這個指標指向了a的首地址
//p++表示每次指向下一個單元的位置
int main()
{
int *p,i,a[10];
p=a;
for(i=0;i<10;i++)
{
scanf("%d",p++);
}
printf("\n");
p=a;
/*因為第一個for迴圈將p的值增加了十次,
即指標P不再指向原來的陣列,
所以輸出的不是你輸入的10個數
也可以改成p =p-10;*/
for(i=0;i<10;i++,p++);
{
printf("%d\n",*p);
}
return 0;
}
//出問題了,我也不知道哪裡出問題了,和rt的程式設計明明一模一樣qaq
之前呼叫使用陣列下標來做索引,現在改為用指標來做索引
#include <stdio.h>
int reverse(int *x,int n)//獲取的是一個指標變數
{
int *p,temp,*i,*j,m;
m=(n-1)/2;
i=x; //i指向陣列的第一個元素(地址)
j=x+n-1; //j指向陣列的最後一個元素
//因為這個陣列是從零開始索引的,所以需要減一
p=x+m; //m等於中間的值 ,指向中間配對
for(;i<=p;i++,j--)
{
temp=*i;
*i=*j;
*j=temp;
}
}
int main()
{
int i,a[10]={3,7,9,11,0,6,7,5,4,2};
printf("The original array:\n");
for(i=0;i<10;i++)
{
printf("%d",a[i]);
}
printf("\n");
reverse(a,10);//作用使得陣列重新倒敘排放
//傳遞的依舊是這個陣列的陣列名
printf("the array has been inverted:\n");
for(i=0;i<10;i++)
{
printf("%d",a[i]);
}
printf("\n");
return 0;
}
/*陣列0,4,9三個地址,然後進行值交換.主函式陣列首地址傳過去相當於
陣列首地址傳過去程式自動識別為指標指向了陣列的首地址
兩種方法都是穿的地址過去的兩個變數分別是陣列首地址和陣列個數
*/
陣列名a相當於此陣列的地址。。。
a[0]的地址傳給指標變數*p,此時*p為定義,不是取值
#include <stdio.h>
void sort(int x[],int n)
{int i,j,k,t;
for(i=0;i<n-1;i++)
{
k=i;
for(j=i+1;j<n;j++)
{
if(x[j]>x[k])
{
t=x[j];
x[j]=x[k];
x[k]=t;
}
}
}
}
int main()
{
int *p,i,a[10]={3,7,9,11,0,6,7,5,4,2};
printf("The original array:\n");
for(i=0;i<10;i++)
{
printf("%d ",a[i]);
}
printf("\n");
p=a;
sort(p,10);
printf("the result is:\n");
for(p=a,i=0;i<10;i++)
{
printf("%d ",*p);
p++;
}
printf("\n");
}
{
int a[3][4]={0,1,2,3,4,5,6,7,8,9,10,11};
printf("a=%d\n",a);//a的地址,a【0 】【0】的地址,也是此二維陣列的地址
printf("*a=%d\n",*a);//表示的是這一個指標變數,與下邊的a【0】相同
printf("a[0]=%d\n",a[0]);//不是0哦!!!!
printf("&a[0]=%d\n",&a[0]);
printf("&a[0][0]=%d\n",&a[0][0]);//前五個都指向同一個地址,只是表達不相同
printf("a+1=%d\n",a+1);//指第二行的第一個地址
printf("*(a+1)=%d\n",*(a+1));
printf("a[1]=%d\n",a[1]);
//只有在輸出a【1】【0】的時候才會輸出4,就是要把名稱寫全
printf("&a[1]=%d\n",&a[1]);
printf("&a[1][0]=%d\n",&a[1][0]);
printf("a+2=%d\n",a+2);//指向a【2】【0】的地址
printf("a[2]=%d\n",a[2]);//同上
printf("a[1]+1=%d\n",a[1]+1);//指向a【1】【1】的地址
printf("*(a+1)+1=%d\n",*(a+1)+1); //同上
printf("*(a[1]+1)=%d\n",*(a[1]+1));//取a【1】【1】的地址
printf("*(*(a+1)+1)=%d\n",*(*(a+1)+1));//取此值
return 0;
}
所以多維陣列指的是在一維陣列上邊的擴充套件,並不是真正的多維陣列
對二維陣列,如果不出現降維符“【】”或“*”,指向二維陣列出現一個降維符號指向一維陣列,出現兩個則指向元素即數值,而a【1】【2】則是元素值
小心別忘了\0這個元素
#include <stdio.h>
void copy_string(char *from,char *to)
{
while((*to=*from)!='\0')
{
to++;
from++;
}
*to='\0';
}
/*錯因::while(*(from+i)!='\0')
{
*(to+i)=*(from+i);
i++;
}
*to='\0';
}*/
int main()
{
void copy_string(char *from,char *to);
char *a="im a student";
char b[]="you are a liar";//*b就不能執行
/*因為是b背寫(被copy了) ,
如果使用指標變數來存放一段字串,
他是直接將一段字串的偏移地址存放,是整句整句的存放
而陣列是一個字元一個字元的存放。
指標存放地址是一個常量區,我們不能去改變常量區的值*/
printf("string a == %s\nstring b=%s\n",a,b);
printf("copy string a to string b:\n");
copy_string(a,b);
printf("\nstring a=%s\nstring b=%s\n",a,b);
return 0;
}
字串在記憶體中儲存在常量裡面。這樣寫相當於把常量的地址給陣列,然而陣列的地址是不可以修改的。而非單純的亂碼等價的問題
這個字元陣列已經是定義好了的了,我們完全可以把輸入的字存放到這個字串裡邊去
正解: 錯誤原因是:未初始化就使用了區域性指標變數a !
想要輸出字串後邊的部分,直接+相應的數目即可,不用*,這樣去的僅僅只是一個字元的地址。
#include <stdio.h>
int main()
{
int max(int,int);
int min(int,int);
int add(int,int);
void process(int x,int y,int(*fun)(int,int));
int a,b;
printf("endter a and b:");
scanf("%d%d",&a,&b);
printf("max=");
process(a,b,max);
printf("min=");
process(a,b,min);
printf("sum=");
process(a,b,add);
return 0;
}
int max(int x,int y)
{
int z;
if(x>y)
{
z=x;
}
else
{
z=y;
}
return z;
}
int min(int x,int y)
{
int w;
w=x<y?x:y;
return w;
}
int add(int w,int z)
{
int x;
x=w+z;
return x;
}
void process(int x,int y,int (*fun)(int,int))
{
int result;
result=(*fun)(x,y);
printf("%d\n", result);
}
process函式不需要用if判斷指標指向的函式,int main主函式裡面已經給指標賦予了一個新函式,直接用指標函式就行
#include <stdio.h>
int *search(int (*stu)[4]); //定義搜尋函式
int main()
{
int stu[3][4], i, j, *p;
for (i=0; i<3; i++)
for (j=0, printf("Please enter No.%d student score: ", i+1);
j<4; scanf("%d", &stu[i][j++])); //輸入全部學生成績
for (i=0; i<3; i++){ //迴圈判斷3個學生的成績
p=search(stu+i); //呼叫搜尋函式
if (p==*(stu+i)){
for(j=0, printf("No.%d student is fail!\nScore: ", i+1);
j<4; printf("%d ", *(p+j)), j++); //輸出不及格成績的學生成績及學生號。
printf("\n");
}
}
return 0;
}
//搜尋函式
int *search(int (*stu)[4])
{
int *fail, i;
for (i=0, fail=NULL; i<4; *(*stu+i)<60 ? fail=*stu, i++ : i++);
return fail;
}
法二:
#include <stdio.h>
int main(void)
{
float score[][4]={{60,70,80,90},{56,89,67,88},{34,78,90,66}};
float *search(float (*p1)[4]);
float *p;
int i,j;
for(i=0;i<3;i++)
{
p=search(score+i);//如果不及格就返回score[i][0]的地址,否則返回null
if(p==*(score+i))//如果沒有小於60的就返回null
{
printf("%d\tscore:",i);
for(j=0;j<4;j++)
{
printf("%f\t",*(p+j));
}
printf("\n");
}
}
return 0;
}
float *search(float (*p1)[4])//判斷成績是否及格
{
int i=0;
float *pt;
pt=NULL;
for(;i<4;i++)
{
if(*(*p1+i)<60)
{
pt=*p1;
}
}
return pt;
}
重點通常在後邊
#include <stdio.h>
#include <stdlib.h>
void main (int argc, char *argv[])
{
int i;
printf ("the number of string is : %d\n", argc-1);
for(i=1; i < argc; i++)
{
printf ("the string %d is : %s\n", i, argv[i]);
}
}
argc是int型的,它用來存放命令列引數的個數,argv是一個一維的一級指標陣列,它是用來存放命令列中各個引數和命令字的字串,這些都包含檔名
/* MEMCPY.C: Illustrate overlapping copy: memmove
* handles it correctly; memcpy does not.
*/
#include <memory.h>
#include <string.h>
#include <stdio.h>
char string1[60] = "The quick brown dog jumps over the lazy fox";
char string2[60] = "The quick brown fox jumps over the lazy dog";
/* 1 2 3 4 5
* 12345678901234567890123456789012345678901234567890
*/
void main( void )
{
printf( "Function:\tmemcpy without overlap\n" );
printf( "Source:\t\t%s\n", string1 + 40 );
printf( "Destination:\t%s\n", string1 + 16 );
memcpy( string1 + 16, string1 + 40, 3 );
printf( "Result:\t\t%s\n", string1 );
printf( "Length:\t\t%d characters\n\n", strlen( string1 ) );
/* Restore string1 to original contents */
memcpy( string1 + 16, string2 + 40, 3 );
printf( "Function:\tmemmove with overlap\n" );
printf( "Source:\t\t%s\n", string2 + 4 );
printf( "Destination:\t%s\n", string2 + 10 );
memmove( string2 + 10, string2 + 4, 40 );
printf( "Result:\t\t%s\n", string2 );
printf( "Length:\t\t%d characters\n\n", strlen( string2 ) );
printf( "Function:\tmemcpy with overlap\n" );
printf( "Source:\t\t%s\n", string1 + 4 );
printf( "Destination:\t%s\n", string1 + 10 );
memcpy( string1 + 10, string1 + 4, 40 );
printf( "Result:\t\t%s\n", string1 );
printf( "Length:\t\t%d characters\n\n", strlen( string1 ) );
}
#include <stdio.h>
void main(void)
{
const char *str= "Welcome to Fishc.com!\n\n";
// 這個語句的含義是:宣告一個名為str的指標變數,
// 它指向一個字元型常量,初始化str為指向字串
// "Welcome to Fishc.com!\n\n"
printf("\n\n%s", str);
#if (1)
str[0] = 'w'; //這條語句是錯誤的,但可以改變str指標的值
#endif
str = "I love Fishc.com!\n\n"; //合法!
printf("\n\n%s", str);
#include <stdio.h>
void main(void)
{
char * const str = "Welcome to Fishc.com!\n\n";
// 常量指標是一個固定的指標,不可以改變它的值,但它所指的資料可以改變。
str[0] = 'w'; //合法!
#if( 1 )
str = "I love Fishc.com!\n\n"; //非法!!
#endif
printf("\n\n%s", str);
}
可以定義const常量,具有不可變性。例如:const int Max=100; Max++會產生錯誤
const在*後表示地址為變數,該地址指向的值是可變的
#include <stdio.h>
void main(void)
{
const char * const str = "Welcome to Fishc.com!\n\n";
// 常量指標是一個固定的指標,不可以改變它的值,但它所指的資料可以改變。
str[0] = 'w'; //非法!
str = "I love Fishc.com!\n\n"; //非法!!
printf("\n\n%s", str);
}
相關文章
- C----陣列越界問題、指標入門陣列指標
- C++入門解惑(2)——初探指標(上) (轉)C++指標
- C++入門解惑(3)——初探指標(下) (轉)C++指標
- 常見指標型別入門指標型別
- C指標原理(15)-C指標基礎指標
- C指標原理(14)-C指標基礎指標
- C | 指標指標
- C/C++指向指標的指標C++指標
- C++ this 指標C++指標
- C++ 指標C++指標
- C語言指標(三):陣列指標和字串指標C語言指標陣列字串
- 再學C/C++ 之 指標常量 和 常量指標C++指標
- C與指標 第六章 指標指標
- C語言指標(二) 指標變數 ----by xhxhC語言指標變數
- C++指標理解C++指標
- C語言(指標)C語言指標
- 【c++】智慧指標C++指標
- C 指標有害健康指標
- C指標錯誤指標
- C++智慧指標C++指標
- C語言指標C語言指標
- C/C++指標總結C++指標
- C++入門經典第九章指標第一節自測題C++指標
- C語言指標安全及指標使用問題C語言指標
- C++中的this指標C++指標
- c++ 函式指標C++函式指標
- C++引用和指標C++指標
- C語言-指標操作C語言指標
- C#中使用指標C#指標
- C++11 智慧指標C++指標
- C++指標轉換C++指標
- C++指標問題C++指標
- 「C++」理解智慧指標C++指標
- C#指標型別C#指標型別
- c++指標小計C++指標
- c指標之字串常量指標字串
- C++(函式指標)C++函式指標
- C陣列和指標陣列指標