2013年10月20日 星期日

week4- 形容詞&副詞子句應用

module 1:
I live in Taiwan, which has plenty of delicious food and beautiful landscapes. Although Taiwan is a tiny island surrounded by ocean, it  is still abundant in natural resources. Due to the limitation of ground where people can live, the cities in Taiwan usually have high population. Therefore, the culture of night market grows rapidly in Taiwan such that people can enjoy  a variety of small eats even though it's midnight. "Taipei travel essentials: passport, cash, extra stomach",  which CNN had published before, recommends 40 Taiwanese foods we can't live without. For instance, Bubble tea, the most fabulous drink with tapioca balls, is one of the most representative small food in Taiwan.  Except for small food, Taiwanese also wins reputation of being hospitable and enthusiastic. You can experience our enthusiasm wherever you go, so come and visit our beautiful island, Taiwan.

module 2 :
In my opinion, natural disasters are a huge disadvantage of Taiwan. One of natural disasters is typhoon, consisting of a tropical cyclone. In summer, typhoons, bringing an enormous rainfall and a strong breeze, will come and cause a serious damage to our crops. On account of the damage, our agricultural economic losses hundreds of million dollars each year. Besides, concerning about the shortage of fruits and vegetables, people will buy lots of food before the coming of typhoon, leading to a rise of food prices. Furthermore, villages beside the mountains will risk losing their houses due to mudflows and landslides. To ensure security of residents, government will withdraw all of them by a strong hand to the safer place. Another natural disaster is earthquake,known for its unpredictable occurrence and intense destructive power. People cannot run out of the house immediately while earthquake occurs.When it comes to an huge earthquake, the ground will rumble with house shaking violently. Few seconds later, the houses will collapse rapidly that almost no one can survive. Natural disasters are unavoidable, the most important thing to do is to reduce the damages as best as we can.

2013年10月13日 星期日

Week3

module1:
This restaurant is famous for its seafood and well-serviced quality.Customers have to make a reservation before dining.There are many kinds of seafood on the menu,such as fried-shrimps,roasted-lobster, and steamed-fish.Everyone enjoys their meals there. Due to the fresh seafood and its low price, this restaurant gains high popularity in this small town.

module2: (underline action verbs)
This restaurant is famous for its seafood and well-serviced quality.Customers have to make a reservation before dining.There are many kinds of seafood on the menu,such as fried-shrimps,roasted-lobster, and steamed-fish.The main chef strongly recommends the  roasted-lobster with butter  for main course. The lobster with fragrant butter tastes delicious that everyone enjoys it there. Due to the fresh seafood and its low price, this restaurant gains high popularity in this small town.

Assignment (improvement) :
This restaurant is famous for its seafood and well-serviced quality. There always has a long line of people outside the door, waiting for tasting seafood expectantly. Customers have better to make a reservation before dining. There are many kinds of seafood on the menu, such as fried-shrimps, roasted-lobster, and steamed-fish. The main chef strongly recommends the roasted-lobster with butter for main course due to its freshness. The lobster with fragrant butter tastes delicious that everyone enjoys it there. Due to the fresh seafood and its low price, this restaurant gains higher and higher popularity in this small town. Therefore, the local tourism also gets stronger and brings economic recovery of the town.

2013年9月1日 星期日

Linux Device Driver - IOCTL (copy_to_user & copy_from_user)

在 linux/include/linux/fs.h 中定義許多file operation能用的handler
這一次我針對的是 read、ioctl做練習
file operation中沒實做到的handler會被定義成NULL
這一支程式會先得到來自kernel的回應,接著kernel 換更改指定的數字

先大概說一下主要概念
我要先寫一個mydev.c 當作 driver
執行完make 之後 就把 mydev.ko 加入到 kernel中
此時的 mydev.ko 就是模組, 一個在kernel中的模組了
那要如何與此模組互動呢?
我要再寫一個 test_mydev.c 當作 user
直接把他 gcc 產生執行檔 再指定我要跟mydev 模組溝通

首先先來看 ioc.h
這裡定義了 user 能夠透過 ioctl 傳達的指令
IOC_MAGIC 是device 的 major number , 而我定義其major number為 k
每一個裝置都有其major number 與 minor number
接著我設置 SETNUM  GETNUM  XNUM 3種指令
_IOW  _IOR  _IOWR 是 kernel 的巨集 , 我們用這3個巨集來定義我們的命令要做哪些事
各聚集裡的1,2,3 是自訂的minor number

#ifndef IOC_H
#define IOC_H

#define IOC_MAGIC 'k'
#define SETNUM _IOW(IOC_MAGIC, 1 , int)
#define GETNUM _IOR(IOC_MAGIC, 2 , int)
#define XNUM _IOWR(IOC_MAGIC,3 , int)
#define IOC_MAXNR 3

#endif


接著看到最主要的 driver code : mydev.c
在file operations 中定義了我自訂的操作函數
dev_open : 在user open  device file 時會被呼叫
dev_close : 在user close device file 時會被呼叫
dev_ioctl  :  switch case 中寫了各種command該執行的動作
         若user 呼叫 ioctl 時傳入 SETNUM 則 driver 會將傳入的資料(args)取出,並指定給val 變數
         若user 呼叫 ioctl 時傳入 GETNUM 則 driver 會將val 變數傳出(args)
         若user 呼叫 ioctl 時傳入XNUM 則 driver 會將 user 輸入的數值指派給val變數達到更改資料
         的目的
         (因為user space 與 kernel space 儲存data的空間不同, 因此要用 copy_to_user 與
         copy_from_user來轉遞資料)
dev_read : user 呼叫 read時會被呼叫, 我在這裡放了一個hello字串, kernel會利用copy_to_user 傳到
                 buffer中給user
dev_write: 我在這裡沒用到
init_modules:  程式進入點 , 建立裝置並註冊到kernel
exit_modules: 程式結束 , 移除裝置

#include <linux/init.h>
#include <linux/module.h>

#include <linux/fs.h> //chrdev
#include <linux/cdev.h> //cdev_add() / cdev_del()

#include <asm/uaccess.h> //copy_*_user()

#include "ioc.h"

MODULE_LICENSE("GPL");
MODULE_AUTHOR("IRENE 2013/09/01");
#define DEV_BUFSIZE 1024

static int dev_major;
static int dev_minor;
struct cdev *dev_cdevp = NULL;
static int dev_open(struct inode*, struct file*);
static int dev_release(struct inode*, struct file*);
static int dev_ioctl(struct inode*, struct file*, unsigned int, unsigned long);
ssize_t dev_read(struct file*, char __user*, size_t, loff_t*);
ssize_t dev_write(struct file*, char __user*, size_t, loff_t*);
static void __exit exit_modules(void);

//Functions on the right side are the handler we just defined
struct file_operations dev_fops = {
   .owner = THIS_MODULE,
   .open = dev_open,
   .release= dev_release,
   .ioctl = dev_ioctl,
   .read = dev_read,
   .write = dev_write
};


// dev_open will be Called when user open the device file
static int dev_open(struct inode *inode, struct file *filp)
{
       printk("%s():\n",__FUNCTION__);
       return 0;
}

// dev_release will be Called when user close the device file
static int dev_release(struct inode *inode, struct file *filp)
{
       printk("%s():\n",__FUNCTION__);
       return 0;
}

// mainly io control between user and kernel
// args are pointed to user space's buffer
static int val = 0;
static int dev_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long args)
{
      int tmp, err=0,ret=0;

      if(_IOC_TYPE(cmd) != IOC_MAGIC)
              return -ENOTTY;
      if(_IOC_NR(cmd) > IOC_MAXNR)
              return -ENOTTY;
      if(_IOC_DIR(cmd) & _IOC_READ){
              err = !access_ok(VERIFY_WRITE, (void __user*)args, _IOC_SIZE(cmd));
      } else if (_IOC_DIR(cmd) & (_IOC_WRITE)){
              err = !access_ok(VERIFY_READ, (void __user *)args,_IOC_SIZE(cmd));
      }

      if (err)
              return -EFAULT;

      switch (cmd) {
        case SETNUM:
             //copy data from args(user) to val(kernel)
             if(copy_from_user(&val,(int __user *)args,1))
                 return -1;

             printk("%s():get val from user = %d\n",__FUNCTION__,val);
                   break;
        case GETNUM:
                        //copy data from val to args
              if(copy_to_user((int __user *)args,&val,1))
                    return -1;

              printk("%s():set val to %d\n",__FUNCTION__, val);
                    break;
        case XNUM:
                       // exchange data passed by user
              tmp = val;
              if(copy_from_user(&val,(int __user *)args,1))
                        return -1;

              if(copy_to_user((int __user *)args,&val,1))
                        return -1;

           printk("%s():change val from %d to %d\n",__FUNCTION__,tmp,val);
           break;

        default: /* redundant. as cmd was checked against MAXNR */
                 return -ENOTTY;
     }
     return 0;
}


static const char str[]="Hello Irene from kernel!";
static const ssize_t str_size = sizeof(str);
// send messages to user
ssize_t dev_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
{

     printk("%s():\n",__FUNCTION__);

     if( *f_pos >= str_size)
          return 0;
     if( *f_pos + count > str_size)
        count = str_size - *f_pos;
     if (copy_to_user(buf, str + *f_pos, count))
        return -EFAULT;
     *f_pos += count;
     return count;

}

ssize_t dev_write(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
{
     printk("%s():\n",__FUNCTION__);
     return 0;
}

static int __init init_modules(void)

   dev_t dev;
   int ret;
   // get major number dynamically
   ret = alloc_chrdev_region(&dev, 0, 1, "mydev");
   if (ret <0){
      printk("can't alloc chrdev\n");
      return ret;
   }
   dev_major = MAJOR(dev);
   dev_minor = MINOR(dev);
   printk("register chrdev(%d,%d)\n",dev_major,dev_minor);

   dev_cdevp = kmalloc(sizeof(struct cdev), GFP_KERNEL);
   if (dev_cdevp == NULL){
        printk("kmalloc failed\n");
        goto failed;
   }
   // system call handler
   cdev_init(dev_cdevp, &dev_fops);
   dev_cdevp->owner = THIS_MODULE;
   //register my device to kernel
   ret = cdev_add(dev_cdevp, MKDEV(dev_major, dev_minor),1);
   if(ret < 0){
        printk("add chr dev failed\n");
        goto failed;
   }
   return 0;

failed:
   if(dev_cdevp) {
   kfree(dev_cdevp);
   dev_cdevp = NULL;
}
  return 0;
}


static void __exit exit_modules(void)
{
   dev_t dev;
   dev = MKDEV(dev_major, dev_minor);
   if (dev_cdevp){
      cdev_del(dev_cdevp);
      kfree(dev_cdevp);
    }
   unregister_chrdev_region(dev,1);
   printk("unregister chrdev\n");
}

module_init(init_modules);
module_exit(exit_modules);


接著 是 user 端部分啦 test_mydev.c
執行時要輸入的參數有 devicefile num
device file 就是 在 /dev下的裝置檔名
num 是 XNUM命令時要change的value (default 是 10 )
首先利用 open 打開 device file
然後 read(fd, buffer, sizeof(buffer));
buffer 是 user 拿來放kernel 回傳值的地方
此時kernel 會回傳 Hello Irene from kernel!
接著 user 開始下達 ioctl command
--> ioctl(fd, SETNUM, &ret)
這是其中一個例子 , SETNUM 便是user 下達的command
而&ret 是 回傳值的指標

#include <stdio.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "ioc.h"

int main(int argc, char *argv[])
{
       int fd, ret=10;
       unsigned char buffer[50]={};
       if(argc < 2)
       {
         printf("Usage: /dev/mydev param1.. \n");
         return -1;
       }
       // open dev file
       fd=open(argv[1], O_RDWR);
       if(fd < 0)
       {
           printf("open %s failed\n", argv[1]);
           return -1;
       }
       //read from kernel 
       read(fd, buffer, sizeof(buffer));
       printf("%s\n",buffer);
       // set num to 10
       if (ioctl(fd, SETNUM, &ret)< 0)
       {
           printf("set num failed\n");
           return -1;
       }
       if(ioctl(fd, GETNUM , &ret)< 0)
       {
           printf("get num failed\n");
       }
       printf("get default value=%d\n",ret);
       // exchange number ret =atoi(argv[2]); 
       if (ioctl(fd, XNUM, &ret)<0)
       {
           printf("exchange num failed\n");
           return -1;
        }
       printf("get value = %d\n",ret);
       return 0;
}


最後是 Makefile








上面全部的檔案都存在mydev 資料夾中
/usr/src/kernels/linux-2.6.18/mydev/..

開始執行
make 之後的指令如下












在 insmod之後 dev會被賦予 major number 與 minor number 
開啟新的cmd 執行dmesg就可以看到kernel傳來一條msg
register  chrdev(252,0)
或是可以到 /proc/devices中查看 major number 與 minor number
在mknod時一定要給定對的major 與 minor number
否則會有 找不到 file 的錯誤
執行後可以看到
kernel 傳回一條 hello messages
而kernel也將預設為10 的value改為 user 設定的 100
最後dmesg中可以看到kernel的訊息












研究好多天仍有很多疑問, 有不完備之處之後繼續修改
參考:
 http://csw17.pixnet.net/blog/post/11506143
http://nano-chicken.blogspot.tw/2009/12/linux-modulesv-ioctl.html
http://www.codeproject.com/Articles/112474/A-Simple-Driver-for-Linux-OS
強烈建議大家在寫這個之前先到jollen的網站看相關的 device 觀念教學

2013年8月25日 星期日

Linux Kernel Module 3 - command line argument

1. 由command line傳入的value會被視為global
2. 使用module_param() macro來加入變數
3. 在runtime時, insmod會填入從command line輸入的value到相應的變數
4. module_param()有3個params,依序為 變數名稱, 變數型態, 權限
    module_param(name, type, permission)
   目前支援的type有 byte, short, ushort, int, uint, long, ulong, charp, bool
5.若要傳入array或string可以使用 module_param_array() or module_param_string()
  array的話在type之後要多一個count , module被載入的時候user所指定的array length會被fill到此變
  數中 , NULL也可以
6. 使用 module_param_desc()則可以對某一變數做描述

/*
 * hello_5.c - Demonstrates command line argument passing to a module.
 */
#include &lt;linux/module.h&gt;
#include &lt;linux/moduleparam.h&gt;
#include &lt;linux/kernel.h&gt;
#include &lt;linux/init.h&gt;
#include &lt;linux/stat.h&gt;

MODULE_LICENSE(&quot;GPL&quot;);
MODULE_AUTHOR(&quot;Irene&quot;);

static short int myshort = 1;
static int myint = 420;
static long int mylong = 9999;
static char *mystring =&quot;blah&quot;;
static int myintArray[2]= {6,6};
static int arr_argc = 0;

/*
 * module_param(foo, int , 0000)
 * The first param is the parameters name
 * The second param is it&#39;s data type
 * The final argument is the permissions bits,
 * for exposing parameters in sysfs (if non-zero) at a later stage.
 */

module_param(myshort, short, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
MODULE_PARM_DESC(myshort, &quot;A short integer&quot;);
module_param(myint, int, S_IRUSR | S_IWUSR | S_IRGRP |S_IROTH);
MODULE_PARM_DESC(myint, &quot;An integer&quot;);
module_param(mylong, long, S_IRUSR);
MODULE_PARM_DESC(mylong, &quot;A long integer&quot;);
module_param(mystring, charp, 0000);
MODULE_PARM_DESC(mystring, &quot;A character string&quot;);

/*
 * module_param_array(name, type, num, perm);
 * The first param is the parameter&#39;s (in this case the array&#39;s)name
 * The second param is the data type of the elements of the array
 * The third argument is a pointer to the variable that will store the number
 * of the elements of the array initialized by the user at module loading time
 * The fourth argument is the permission bits
 */
module_param_array(myintArray, int, &amp;arr_argc, 0000);
MODULE_PARM_DESC(myintArray, &quot;An array of integers&quot;);

static int __init hello_5_init(void)
{
int i;
printk(KERN_INFO &quot;Hello, world 5\n==============\n&quot;);
printk(KERN_INFO &quot;myshort is a short integer: %hd\n&quot;, myshort);
printk(KERN_INFO &quot;myint is an integer: %d\n&quot;, myint);
printk(KERN_INFO &quot;mylong is a long integer: %ld\n&quot;, mylong);
printk(KERN_INFO &quot;mystring is a string: %s\n&quot;,mystring);
for(i=0; i&lt;(sizeof myintArray / sizeof(int));i++)
{
printk(KERN_INFO &quot;myintArray[%d] = %d\n&quot;, i,myintArray[i]);
}
printk(KERN_INFO &quot;got %d arguments for myintArray.\n&quot;, arr_argc);
return 0;
}
static void __exit hello_5_exit(void)
{
printk(KERN_INFO &quot;Goodbye, world 5\n&quot;);
}

module_init(hello_5_init);
module_exit(hello_5_exit); 


利用 insmod hello_5.ko 看output messages ( 利用 cat /var/log/messages)








或是 insmod hello_5.ko myint=25 mystring="Irene" myintArray=1,2









可以看到指定的變數都改value了!




2013年8月24日 星期六

Linux Kernel Module 2 - 顯示 module info

在 Linux  /include/linux/module.h 中可以找到定義一些module基本info的function
for example:

 MODULE_DESCRIPTION(DESC) : 定義MODULE在做些什麼
 MODULE_AUTHOR(AUTHOR) : 明顯的就是告訴大家作者是誰
 MODULE_LICENSE(GPL) : 宣告GPL

至於上面的DESC 和 AUTHOR 可以用 #define 來預先定義
#define DESC "this is description"
#define AUTHOR "I am author"

這是書中 hello_4.c 範例
寫完一樣 make和 insmode
再來執行 modinfo hello_4.ko 就會顯示info了











2013年8月16日 星期五

Linux Kernel Module 1 - 第一支Hello Irene Module

1. 先查詢自己的Linux version
    --> uname -r
    我的版本是 Linux-2.6.18

2. 下載Linux Kernel Source Code (壓縮檔放在/root底下)
     選擇 linux-2.6.18.tar.bz2

3. 把 source code放在 /usr/src/kernels/ 目錄下
    --> tar -jxvf  linux-2.6.18.tar.bz2 -C /usr/src/kernels/
    此時kernels下會有一個linex-2.6.18資料夾

4.進入kernel 目錄
   --> cd /usr/src/kernels/linux-2.6.18

5. 建立存放module的資料夾
   --> mkdir hello

6.開始寫內部程式
   (1) hello-1.c
      --> vim hello-1.c
      --> i  (編輯模式)
      -->按 Esc 回一般模式
      --> :wq (儲存並離開)
     


      (2) Makefile
        --> vim Makefile
        
       


7 --> make
make 之後會產生 hello-1.ko 


8 --> insmod ./hello-1.ko
將hello-1.ko 加入至kernel module中
可以到 /proc/modules/中看到hello-1 module正在kernel中


此時利用 cat /var/log/messages 到messages中會看到 Hello Irene

9. --> rmmod ./hello-1.ko
將hello-1 module移除
此時 /proc/modules/中就看不見 hello-1 module了
而到 /var/log/messages/ 會看到 Goodbye Irene


P.S 想要搜尋Hello與 Goodbye,可使用grep 指令
--> cat /var/log/messages | grep Hello
--> cat /var/log/messages | grep Goodbye

第一次寫kernel的東西~我連linux指令都還不太熟悉@@
希望繼續加油囉!
-------------------------------------------------------------------
參考 :  鳥哥的 Linux私房菜 第三版  ch22,ch26
           The Linux Module Programming Guide 
            





2013年7月11日 星期四

Pointer in C


















圖1
pointer有3種pointer arithmetic
1) result: p指向a[3],q指向a[4]
2) result: p指向a[5],q指向a[7]














圖2
 &b[0] 和 b 一樣代表的是array b的第一個元素














多維陣列也可以想成是一維陣列,ex:第一種寫法
p指向第一個元素,接著一直向下指
多維陣列也是多個一維陣列組成,ex:第二種寫法
i 是row的index
p先指向第一行陣列,c[i]此時代表的是第一行陣列第一個元素的addr
p會先加完第一行所有列的元素在指向第二行

<P.s 1>
終止條件寫成 p< &c[NUM_ROWS][NUM_COLS]可能會有錯
因為c[NUM_ROWS][NUM_COLS]這一個元素已在array c預期的大小之外
因此他的addr可能是一個任意位址
若p的addr剛好小於此元素的位址就會造成錯誤。

<P.s 2>
while(*a!=0)
  a++;    //wrong
雖然 a 是 array name也可以當作指標,但不能assign 給 a 新的值
上述 a++指移動位址,因此錯誤
可以給一個 pointer指向a
再移動 p (assign p 新的值)
p=a;
while(*p!=0)
   p++;   //correct


2013年3月16日 星期六

Pointer 2_const

(1)a non-constant pointer to non-constant data

存取權最高
Data可透過pointer遭到更改
Pointer可以改為只向別的物件
Ex: pointer3.c
----------------------------------------------------------------------------------

/* Converting lowercase letters to uppercase letters
using a non-constant pointer to a non-constant data */
#include <stdio.h>
#include <ctype.h>
void convertToUppercase(char *ptr);
int main(void)
{
char string[]="characters and $32.25";
printf("The string before conversion is: %s",string);
convertToUppercase(string);
printf("\nThe string after conversion is:%s\n",string);
return 0;
}
void convertToUppercase(char *ptr)
{
while(*ptr !='\0')
{
if(islower(*ptr))
{
*ptr=toupper(*ptr);
}
++ptr;
}
}
-------------------------------------------------------------------------------------------
(2)a non-constant pointer to constant data

Ex: pointer5.c
若隨意更改指標指向的物件內容會有error
編譯錯誤: assignment of read only location “ptr
明顯的問題出在ptr指向的是read only的位置,不能更改
Tips: 陣列當引數呼叫function時,陣列會自動以傳參考呼叫function,struct則是永遠以傳值的方式,傳遞整個副本過去會造成執行的負擔,因此必須將struct傳給函式時使用指向constant data的指標,一方面獲得傳參考呼叫的效率,一方面能保護資料。也就是說只要複製一份struct本身的位址就好。--一個時間/空間取捨(time/space trade-off)的例子
Important: memory 不夠大且執行效率很重要時,用指標
memory 很大且效率不那麼重要,用call by value實行最小權限原則
-----------------------------------------------------

/* Attempting to modify data through a non-constant pointer to constant data */
#include<stdio.h>
void f(const int *ptr);

int main (void)
{
int y;
f(&y);
return 0;
}
/* ptr cannot be used to modify the value of variable to which it points */
void f(const int *ptr)
{
*ptr=100; //error: cannot modify a const object
}

-----------------------------------------------------------------------------------------------
(3)a constant pointer to a non- constant data

非常數指標的常數指標永遠會指向同一個記憶體位置,不過指標所指向的數值可以更改。
Array名稱預設就是這種指標。
Const的指標必須在宣告時指定初始值
若指標是函式的參數,則初始值將設成傳入此函式的指標
Ex:pointer6.c
Ptr是一個指向整數的常數指標,但後來又指向y,此時編譯器會error—assignment of read only variable “ptr
-------------------------------------------------------------------------------------------------------------------

/* Attempting to modify a constant pointer  to a non-constant data */
#inlcude <stdio.h>
int main(void)
{
int x;
int y;
/* ptr is a constant pointer to an integer that can be modified through ptr,
but ptr always points to the same memory lacation */
int *const ptr=&x;
*ptr=7;
ptr=&y;

return 0;
}

-------------------------------------------------------------------------------------------------------------------
(4)a constant pointer to a constant data

存取權最低
Pointer永遠指向同一個記憶體位置,且該位置內容不能更改
Ex: pointer7.c
  Const int *const  ptr=&x;
  Ptr是一個常數指標,指向一個整數常數
  程式中藥更改指標與指標指向的內容都失敗 Assignment of read only  location “ptr”  Assignment of read only  variable “ptr
-----------------------------------------------------------------------------------------------------------------

/* Attempting to modify a constant pointer to constant data */
#include<stdio.h>
int main(void)
{
int x=5;
int y;

/*ptr is a constant pointer to a constant integer.ptr always
points to the same location;the integer at that location
cannot be modified */
const int *const ptr=&x;
printf("%d\n",*ptr);
*ptr=7; //error : *ptr is const;cannot assign new value 
ptr=&y; //error:  ptr is const;cannot assign new address
return 0;
}

-----------------------------------------------------------------------------------------------------------------



Pointer 1_basic

1) 指標可以指定0,NULL,或某個位址
2) & operator為取址運算子(address operator)-會回傳operator address的 一元運算子,不能應用到
      常數、運算式或宣告為register的變數
3) * operatorindirection operator or dereferencing operator(間接或是反參考運算子)-回傳運算元
      所指向的物件的
4) ex:pointer1.c
  - %p: 將記憶體位址以16進制印出
  - &和*是互補的,同時使用的話就是顯示指標內容







5) C語言中所有的引數都是以值進行傳遞
6)
Call by value Call by reference
7)
許多函式需要具有修改呼叫函式內定義之變數的能力,或傳遞一個指向大型物件的指標來
     避免因為call by value所產生的額外負擔。因此C提供simulating call-by-reference的功能
8)
引數加上&來傳遞變數位址,而函式內部用*即可改變變數內容
9)
陣列名稱相當於&array[0]C會自動傳遞陣列的起始位址,所以當陣列是引數時不用加&



















10) const修飾詞:告訴編譯器變數不能被修改
11)
軟工觀點:const 可實現最小權限原則,減少偵錯時間,使程式更容易維護。
12)
函式的參數使用const6種方式,可利用principle of least privilege作為挑選原則。
      <1> a non-constant pointer to non-constant data
                  指向非常數資料的非常數指標
      <2> a constant pointer to non-constant data
                  指向非常數資料的常數指標
      <3> a non-constant pointer to constant data
                  指向常數資料的非常數指標
      <4> a constant pointer to constant data
                  指向常數資料的常數指標

全國推廣動物認領養平台串聯貼紙

全國推廣動物認領養平台串聯貼紙