Navigationskarta Insitutitionen för Datavetenskap Umeå Universitet

Kodexempel F6

Invecklade deklarationer - inte så svårt som det ser ut!

"Hur deklarerar jag en funktion som tar en pekare till pekare till const int och r eturnerar en pekare till en array av pekare till const char?"
f är en funktion...
  f()
...som tar en pekare till pekare...
  f(**)
...till const int...
  f(const int **)
...och returnerar pekare...
  *f(const int **)
...till array...
  (*f(const int **))[]
...av pekare...
  *(*f(const int **))[]
...till const char.
  const char *(*f(const int **))[]
Kom ihåg att läsa inifrån och ut, och glöm inte skillnaderna i prioritet!

Den bild jag ritade på minneslayouten i en Unix-process finns i "Advanced Programming in the UNIX Environment", kapitel 7.


...
#include <sys/types.h>
#include <unistd.h>
...
pid_t pid;
...
if ((pid =fork()) < 0) {
	perror("Couldn't fork()");
	exit(1);
} else if (pid == 0) {
	printf("Child. PID = %d, PPID = %d.\n", \
			(int)getpid(), (int)getppid());
} else {
	printf("Parent. PID = %d, PPID = %d.\n", \
			(int)getpid(), (int)getppid());
}
printf("Hello!\n");
...


Här visade jag ett OH-blad på den bild över C-programs start och stopp i Unix, som finns i kapitel 7 i "Advanced Programming in the UNIX Environment".


#include <sys/types.h>
#include <sys/wait.h>

pid_t wait(int *status);
pid_t waitpid(pid_t pid, int *status, int options);


WEXITSTATUS(status)
WIFEXITED(status)
WIFSIGNALED(status)
WIFSTOPPED(status)


#include <unistd.h> int execl(const char *path, const char *arg0, ..., const char *argn, (char *)0); int execv(const char *path, char *const *argv); int execle(const char *path, const char *arg0, ..., const char *argn, (char *0), char *const envp[]); int execve(const char *path, char *const *argv, char *const envp[]); int execlp(const char *file, const char *arg0, ..., const char *argn, (char *)0);

Ett litet exempel på hur ett execvp()-anrop kan se ut:

char *args[] = {"netscape", "-install", NULL};
...
if (execvp(args[0], args) < 0) {
	perror(args[0]);
	exit(1);
}

Om args[0] börjar med '/' så tolkar execvp argumentet som en full sökväg till ett program. Annars söker execvp i de kataloger som anges i miljövariabeln PATH efter en körbar fil med namnet som anges av args[0].
Men är det verkligen nödvändigt med if-kollen? Nej, för om execvp returnerar överhuvudtaget gick något fel. Alltså kan det lika gärna se ut så här:

char *args[] = {"netscape", "-install", NULL};
...
execvp(args[0], args);
perror(args[0]);
exit(1);

...och ett litet exempel på hur ett execle()-anrop kan se ut (denna OH visade jag inte på föreläsningen):

char *my_env[] = {"USER=psycho", "X=yes", NULL};
...
if (execle("/bin/sh", "shp", "/tmp/skript", NULL, my_env) < 0) {
	perror("/bin/sh");
	exit(1);
}

Notera att de två första argumenten till execle() inte behöver vara likadana. Detta kan vara till nytta om ett och samma program uppför sig olika beroende på vilket namn som står i argv[0].


#include <sys/types.h>
#include <unistd.h>

int setuid(uid_t uid);
int setgid(gid_t gid);

int seteuid(uid_t euid);
int setegid(gid_t egid);

uid_t getuid(void);
gid_t getgid(void);

uid_t geteuid(void);
gid_t getegid(void);

[an error occurred while processing this directive]