Month: October 2014

Lỗi redefine khi include nhiều Interface.

Giả dụ ta include 2 interface như sau, trong 2 interface này lại define 1 marcro có tên giống nhau.

Interface 1: baba.h


#ifndef baba
#define baba 6
#endif

Interface 2: baba1.h


#include "baba.h"
#define baba 5
#endif

Include 1 interface trên vào 1 file C để compile như sau.

#include <stdio.h>
#include "baba1.h"
main(){
printf("baba=%d \n",baba);
}

Lúc này khi compile ta nhận được lỗi.

baba1.h:2:0: warning: "baba" redefined

tóm lại, khi mà 1 interface này bao gồm 1 interface khác và 2 interface cùng define 1 macro có tên giống nhau thì sẽ dẫn đến lỗi redefine do ta khai báo hay định nghĩa nhiều lần. Để tiện lợi cho việc sử dụng các interface dùng chéo nhau ( nested) thì ra sẽ sửa lại code trên bằng cách dùng các Condition Inclusion.

Sửa lại file baba1.h


#include "baba.h"
#ifndef baba
#define baba 5
#endif

Ta đã dùng #if để check xem là Macro baba đã được define hay chưa ( trong trường hợp này là rồi, do đã include baba.h trước) vậy khi chạy file C ta sẽ có baba=6, nếu #include “baba.h” được đặt sau #if/#endif thì sẽ có baba=5 do giá trị baba được lệnh tại lệnh


#define baba 5

trong file baba1.h, lệnh này check marco baba nếu chưa được define thì ta define marco baba=5, lệnh #include “baba.h” đặt sau không có tác dụng.

🙂

Statement exprs in C

Dựa vào link sẽ giải thích được pitfall khi dùng #define trong C.

Ta thường dùng #define 1 marcro để tính max 2 số rất nhanh gọn như sau


#define max(i,j) (i&gt;j)?i:j

Macro trên có điểm cần lưu ý là khi ta muốn vừa sử dụng để tính max 2 biến, đồng thời muốn tăng hoặc giảm 2 biến đó luôn. ví dụ


int i=4,j=5,max;
max=max(i++,j++);

printf(&quot;i=%d j=%d max=%d &quot;,i,j, max);

sẽ cho kết quả là


int i=4,j=7,max=6;

Vậy ta thấy thằng j đã bị tăng (++) 2 lần để có giá trị j=7 trong khi ta muốn sau lệnh max thì i=5,j=6,max=5. Có thể lý giải như sau khi #define max(i,j) (i>j)?i:j và invoke nó là max(i++,j++). Ta sẽ có :


max(i++,j++) tương đương (i++&gt;j++)?(i++):(j++)

và như vậy sau khi có (4++>5++) thì sẽ được max=(j++) -> max=6 và j=7.

Để không bị lỗi này ta làm như link trên, đó là define các biến khác có giá trị của các biến trong khi gọi Marcro ví dụ

#define maxint(a,b) \ ({int _a = (a), _b = (b); _a &gt; _b ? _a : _b; })

Chạy lại lệnh sau ta sẽ có i=5, j=6, max=5, đúng như mong muốn.

Ngoài ra khi define 1 marco ta cũng nên lưu ý việc cần sử dụng các dấu ngoặc.

ví dụ


#define square(x) x*x

Code chạy tốt nếu không có size effect, nếu có thì đọc link này để hiểu rõ hơn. 🙂

http://stackoverflow.com/questions/10820340/the-need-for-parentheses-in-macros-in-c

Ví dụ nốt vài phát ở chap4.

#define con(a,b) a##b

Điều này tức là ta concatenate 2 argument thành một biến mới là ab.

Ví dụ


int ab=1;

printf("ab= %d",con(a,b));

Sẽ cho ra kết quả ab=1, :).

Padding các ký tự khác 0 và spaces trong C

Như đã biết, trong C thì khi ta in 1 string có độ dài nhỏ hơn length ta cho trong format của lệnh `printf` thì chuỗi in ra sẽ được pad thêm space hoặc 0 tùy chọn.

ví dụ:


printf("%15s","blah");

sẽ cho ra kết quả sau


(11 spaces)           blah

ta có thể pad các ký tự vào khoảng trắng trước `blah` bằng các ký tự khác như @,#,^,&amp; …


main()
{
char *s="@@@@@@@@@@@@@";
printf("%.3s%s",s,"blah");
}

và kết quả là

@@@blah

Block Structure trong C.

Lâu nay khi dùng biến trong C mình luôn theo style cần gì dùng đó, khai báo hết các biến ở đầu rồi dùng thôi thế nên cũng chẳng bao giờ đi khai báo 1 biến ở giữa thân 1 hàm nào cả.

Hôm nay có code linh tinh một tí thì bị lỗi redifinition ( khai báo lại 1 biến đã khai báo), nhưng code đang viết đã khá dài, dùng khá nhiều biến do vậy mình không muốn khai báo và tạo thêm một biến mới để sử dụng, may thay đoạn code đang viết đang ở trong 1 block ( 1 vòng lặp) do vậy có thể khai báo và tạo một biến có tên tương tự để dùng, sau block này thì biến mất đi.

Đọc thêm phần 4.8 trong sách C programing K&R.

Ví dụ có đoạn sau:


#include<stdio.h>
main()
{
int i=3,n=6;
if(n>5)
{
        i=7;
}
printf(" i= %d \n",i);
}

au

Kết quả in ra là i=7.

Nhưng nếu ta thêm thay i=7 bằng int i=7 ( tức đã khai báo và tạo lại biến i, do ở trong một block nên sẽ không bị lỗi redifinition) như sau

 

#include<stdio.h>
main()
{
int i=3,n=6;
if(n>5)
{
       int i=7;
}
printf(" i= %d \n",i);
}

Kết quả nhận được sẽ là i=3, do khi kết thúc lệnh IF cùng block của nó thì biến i khởi tạo trong nó sẽ không còn. Biến i trong lệnh printf là biến i đã được tạo lúc đầu.