本文目錄一覽:
- 1、linux環境c語言編程!問題棘手!高手進!
- 2、linux c語言文件操作下,文件指針不用FILE*定義而是用int整型定義 (以下是一本書上的例程)
- 3、linux下c語言編程出現段錯誤
- 4、Linux下的C語言編程,怎麼讀取16進制數
- 5、在LINUX下C語言編程調用這個函數int open(argv[1],O_CREAT|O_RDWR,0755) 執行時參數是怎樣給定的?
- 6、linux c 引用傳遞參數
linux環境c語言編程!問題棘手!高手進!
【第一個問題】
argv[i]越界了,不能保證都是null,改成這樣
for(i=1;iargc;i++)
demo[i-1]=atoi(argv[i]);
for(–i;i3;++i)
demo[i]=10;
【第二個問題】
我的理解是第一個子進程wakeup的瞬間,其他的子進程還是sleep,因此第一個子進程執行了printf
優先級再高的進程sleep了也搶不過優先級低的活動進程
因此最好保持3個子進程同時活動
else//子進程執行代碼
{
sleep(1);//為了父進程順利啟動3個子進程,sleep還是留着吧
for(i=1;i;i++);//保持活動一段時間
//報告進程號和優先級
printf(“child %d priority=%d\n”,getpid(),getpriority(PRIO_PROCESS,0));
exit(EXIT_SUCCESS);
//return EXIT_SUCCESS;
}
linux c語言文件操作下,文件指針不用FILE*定義而是用int整型定義 (以下是一本書上的例程)
不要弄混open()和fopen():
open() 是底層系統調用,返回值為文件描述符, (int)
fopen() 是庫函數, 返回值為流指針(FILE *)
fopen() 的實現也是調用的open()函數, 可以理解成對底層調用的一個高層封裝.
linux下c語言編程出現段錯誤
簡單看了一下你的程序
首先,你沒有給出完整的程序,這個讓大夥看起來確實不方便,因為沒有main函數,可能踩內存的地方並不是這個函數本身,是main函數
其次說你的這個函數,貌似確實有點問題,但是由於沒有完整的程序,我只說出我的理解,如果有錯,直接忽視就好
sprintf(flag_height,”%03d”,i+1);
sprintf(flag_width,”%03d”,j+1);
我覺得問題出在這裡,你查下 sprintf 的用法,第一個參數應該是一個字符串的首地址,你寫的確實沒有錯,參數給入的是一個地址flag_height,但是縱觀你的程序,你並沒有給這個指針賦值,程序運行到這裡,估計在默認創建指針的時候應該賦值為NULL(貌似根據編譯器不同而有不同),那個尋址後報出段錯誤,也是意料之中了
由於沒有你完整的代碼,不知道你要做什麼,修改意見不好提
給出個人意見,僅供參考
如果要打印flag_height中的值,首先應該給flag_height指針分配一片內存,使用malloc函數,其次在向內從中寫入值,然後調用sprintf,就應該沒有問題了
Linux下的C語言編程,怎麼讀取16進制數
#include stdio.h
#include string.h
#include sys/types.h
#include errno.h
#include sys/types.h
#include fcntl.h
#include unistd.h
#include termios.h
#include stdlib.h
#define BUFFER_SIZE 1024
#define HOST_PORT 0
int set_port(int fd, int baud_rate, int data_bits, char parity, int stop_bits)
{
struct termios newtio,oldtio;
if( tcgetattr(fd,oldtio) != 0)
{
perror(“Setup Serial 1”);
return -1;
}
bzero(newtio,sizeof(newtio));
newtio.c_cflag |= CLOCAL | CREAD;
newtio.c_cflag = ~CSIZE;
/* set baud_speed*/
switch(baud_rate)
{
case 2400:
cfsetispeed(newtio,B2400);
cfsetospeed(newtio,B2400);
break;
case 4800:
cfsetispeed(newtio,B4800);
cfsetospeed(newtio,B4800);
break;
case 9600:
cfsetispeed(newtio,B9600);
cfsetospeed(newtio,B9600);
break;
case 19200:
cfsetispeed(newtio,B19200);
cfsetospeed(newtio,B19200);
break;
case 38400:
cfsetispeed(newtio,B38400);
cfsetospeed(newtio,B38400);
break;
default:
case 115200:
cfsetispeed(newtio,B115200);
cfsetospeed(newtio,B115200);
break;
}
/* set data_bits upon 7 or 8*/
switch(data_bits)
{
case 7:
newtio.c_cflag |= CS7;
break;
default :
case 8:
newtio.c_cflag |= CS8;
break;
}
/**/
switch(parity)
{
default:
case ‘N’:
case ‘n’:
{
newtio.c_cflag = ~PARENB;
newtio.c_iflag = ~INPCK;
}
break;
case ‘o’:
case ‘O’:
{
newtio.c_cflag |= (PARODD | PARENB);
newtio.c_iflag |= INPCK;
}
break;
case ‘e’:
case ‘E’:
{
newtio.c_cflag |= PARENB;
newtio.c_cflag = ~PARODD;
newtio.c_iflag |= INPCK;
}
break;
case ‘s’:
case ‘S’:
{
newtio.c_cflag = ~PARENB;
newtio.c_cflag = ~CSTOPB;
}
break;
}
/*set stop_bits 1 or 2 */
switch(stop_bits)
{
default:
case 1:
{
newtio.c_cflag = ~CSTOPB;
}
break;
case 2:
{
newtio.c_cflag |= CSTOPB;
}
break;
}
newtio.c_cc[VTIME] = 0;
newtio.c_cc[VMIN] = 1;
tcflush(fd,TCIFLUSH);
if((tcsetattr(fd,TCSANOW,newtio)) != 0)
{
perror(“com set error”);
return -1;
}
printf(“set UART done!\n”);
return 0;
}
int open_port(int com_port)
{
int fd = 0;
char *dev[] = {“/dev/ttyAMA0”, “/dev/ttyS1”, “/dev/ttyS2″,”/dev/ttyS3”,
“/dev/ttyS4”, “/dev/ttyS5”, “/dev/ttyS6”};
if((com_port 0) || (com_port 6) )
{
printf(“the port is out range”);
return -1;
}
fd = open(dev[com_port], O_RDWR | O_NOCTTY | O_NDELAY);
if(fd 0)
{
perror(“open serial port”);
return -1;
}
if(fcntl(fd, F_SETFL,0) 0)
{
perror(“fcntl F_SETFL”);
return -1;
}
if(isatty(fd) == 0)
{
perror(“isatty is not a terminal device”);
return -1;
}
return fd;
}
int main(void)
{
int fd = 0;
char Buffer[BUFFER_SIZE] = {0};
if((fd = open_port(HOST_PORT)) == -1)
{
perror(“open port”);
return -1;
}
if(set_port(fd,115200,8,’N’,1)== -1)
{
perror(“set port”);
return -1;
}
int ReadByte = read(fd,Buffer,512);
char NFC[1024]=””;
if(ReadByte0)
{
int i;
printf(“readlength=%d\n”,ReadByte);
printf(“The Data is:”);
for (i=0;iReadByte;i++)
{
printf(“%02x “,Buffer[i]);
int lennn = strlen(NFC);
sprintf(NFC+lennn, “%02x “,Buffer[i]);
}
printf(“\n”);
printf(“%s\n”, NFC);
sleep(3);
}
else printf(“Read data failure “);
close(fd);
return 0;
}
在LINUX下C語言編程調用這個函數int open(argv[1],O_CREAT|O_RDWR,0755) 執行時參數是怎樣給定的?
你好,O_CREAT表示在argv[1]中的文件存在時,第三個參數沒用,並且以讀寫將其打開;argv[1]中的文件不存在時,則創建這個文件,並設置文件的權限為755,就是用chmod更改的文件權限,755表示對所有者可讀可寫可執行,對所屬組可讀可執行不可寫,對其他用戶可讀可執行不可寫。
linux c 引用傳遞參數
C/C++函數參數的傳遞方式有三種:值傳遞(pass by value)、指針傳遞(pass bypointer)、引用傳遞(pass by reference)。
C/C++函數參數的傳遞通道是通過堆棧傳遞,默認遵循__cdecl(C聲明方式),參數由調用者從右往左逐個壓入堆棧,在函數調用完成之後再由調用者恢復堆棧。(Win32API遵循stdcall傳參規範的,不在本文討論範圍)
下面是測試代碼
void Swap(__int64* _pnX, __int64* _pnY)
{
__int64 nTemp = *_pnX;
*_pnX = *_pnY;
*_pnY = nTemp;
}
void Swap(__int64 _nX, __int64 _nY)
{
__int64 nTemp = _nX;
_nX = _nY;
_nY = nTemp;
}
void SetValue(__int64 _nX)
{
__int64 nTemp = _nX;
}
// Test001
void GetMemory(__int64* _pBuff)
{
_pBuff = new __int64[4];
}
// Test002
void GetMemory(__int64** _ppBuff)
{
*_ppBuff = new __int64[4];
}
int _tmain(int argc, _TCHAR* argv[])
{
__int64 nA = 0x10;
__int64 nB = 0x20;
// Test to pass by pointer
Swap(nA, nB);
// Test to pass by reference
Swap(nA, nB);
// Test to pass by value
SetValue(nA);
// Test the pointer that points the pointer
__int64* _pArray = NULL;
GetMemory(_pArray);
delete[] _pArray;
_pArray = NULL;
// Test the pointer
GetMemory(_pArray);
return 0;
}
指針傳遞和引用傳遞
// 下面看一下對應的反彙編的代碼(VS版)
__int64 nA = 0x10;
0041370E mov dword ptr [nA],10h
mov dword ptr [ebp-8],0
__int64 nB = 0x20;
0041371C mov dword ptr [nB],20h
mov dword ptr [ebp-18h],0
// Test to pass by pointer
Swap(nA, nB);
0041372A lea eax,[nB]
0041372D push eax
0041372E lea ecx,[nA]
push ecx
call Swap (4111E5h)
add esp,8
// Test to pass by reference
Swap(nA, nB);
0041373A lea eax,[nB]
0041373D push eax
0041373E lea ecx,[nA]
push ecx
call Swap (4111E0h)
add esp,8
// GCC版
0x00401582 +30: lea eax,[esp+0x18]
0x00401586 +34: mov DWORD PTR [esp+0x4],eax
0x0040158a +38: lea eax,[esp+0x1c]
0x0040158e +42: mov DWORD PTR [esp],eax
0x00401591 +45: call 0x401520 Swap(int*, int*)
0x00401596 +50: lea eax,[esp+0x18]
0x0040159a +54: mov DWORD PTR [esp+0x4],eax
0x0040159e +58: lea eax,[esp+0x1c]
0x004015a2 +62: mov DWORD PTR [esp],eax
0x004015a5 +65: call 0x401542 Swap(int, int)
通過上面的反彙編代碼,我們可以看出指針傳遞和引用傳遞在機制是一樣的,都是將指針值(即地址)壓入棧中,調用函數,然後恢復棧。Swap(nA, nB)和Swap(nA, nB);在實際上的彙編代碼也基本上一模一樣,都是從棧中取出地址來。由此可以看出引用和指針在效率上是一樣的。這也是為什麼指針和引用都可以達到多態的效果。指針傳遞和引用傳遞其實都是改變的地址指向的內存上的值來達到修改參數的效果。
值傳遞
下面是值傳遞對應的反彙編代碼
// Test to pass by value
SetValue(nA);
0041374A mov eax,dword ptr [ebp-8]
0041374D push eax
0041374E mov ecx,dword ptr [nA]
00413751 push ecx
00413752 call SetValue (4111EAh)
00413757 add esp,8
因為我的機器是32位的CPU,從上面的彙編代碼可以看64Bit的變量被分成2個32Bit的參數壓入棧中。這也是我們常說的,值傳遞會形成一個拷貝。如果是一個自定義的結構類型,並且有很多參數,那麼如果用值傳遞,這個結構體將被分割為非常多個32Bit的逐個拷貝到棧中去,這樣的參數傳遞效率是非常慢的。所以結構體等自定義類型,都使用引用傳遞,如果不希望別人修改結構體變量,可以加上const修飾,如(const MY_STRUCT _value);
下面來看一下Test001函數對應的反彙編代碼的參數傳遞
__int64* _pArray = NULL;
004137E0 mov dword ptr [_pArray],0
// Test the pointer
GetMemory(_pArray);
mov eax,dword ptr [_pArray]
push eax
call GetMemory (411203h)
0041381B add esp,4
從上面的彙編代碼可以看出,其實是0被壓入到棧中作為參數,所以GetMemory(_pArray)無論做什麼事,其實都與指針變量_pArray無關。GetMemory()分配的空間是讓棧中的臨時變量指向的,當函數退出時,棧得到恢復,結果申請的空間沒有人管,就產生內存泄露的問題了。《C++ Primer》將參數傳遞分為引用傳遞和非引用傳遞兩種,非引用傳遞其實可以理解為值傳遞。這樣看來,指針傳遞在某種意義上也是值傳遞,因為傳遞的是指針的值(1個4BYTE的值)。值傳遞都不會改變傳入實參的值的。而且普通的指針傳遞其實是改變的指針變量指向的內容。
下面再看一下Test002函數對應的反彙編代碼的參數傳遞
__int64* _pArray = NULL;
004137E0 mov dword ptr [_pArray],0
GetMemory(_pArray);
004137E7 lea eax,[_pArray]
004137EA push eax
004137EB call GetMemory (4111FEh)
004137F0 add esp,4
從上面的彙編代碼lea eax,[_pArray] 可以看出,_pArray的地址被壓入到棧中去了。
然後看一看GetMemory(_pArray)的實現彙編代碼。
0x0040159b +0: push ebp
0x0040159c +1: mov ebp,esp
0x0040159e +3: sub esp,0x18
0x004015a1 +6: mov DWORD PTR [esp],0x20
0x004015a8 +13: call 0x473ef0 _Znaj
0x004015ad +18: mov edx,DWORD PTR [ebp+0x8]
0x004015b0 +21: mov DWORD PTR [edx],eax
0x004015b2 +23: leave
0x004015b3 +24: ret
藍色的代碼是分配臨時變量空間,然後調用分配空間函數分配空間,得到的空間指針即eax.
然後紅色的彙編代碼即從ebp+0x8的棧上取到上面壓入棧中的參數_pArray的地址.
mov DWORD PTR [edx],eax即相當於把分配的空間指針eax讓edx指向,也即讓_pArray指向分配的空間eax.
總之,無論是哪種參數傳遞方式,參數都是通過棧上的臨時變量來間接參與到被調用函數的。指針作為參數,其本身的值是不可能被改變的,能夠改變的是其指向的內容。引用是通過指針來實現的,所以引用和指針在效率上一樣的。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/258545.html