|
| const char * og char *const * Fra : Soeren Sandmann |
Dato : 12-01-02 21:14 |
|
Jeg har lige skrevet nedenstående funktion, men jeg er ikke tilfreds
med at jeg er nødt til caste til (char *const *) for at oversætteren
vil acceptere det.
Hvad er forskellen på const char * og char *const *?
static void
start_process (const string& cmd_line, int write_end)
{
char env_string[1024];
snprintf (env_string, sizeof (env_string),
"SPROF_MASTER_PIPE=%d", write_end);
putenv (env_string);
snprintf (env_string, sizeof (env_string),
"LD_PRELOAD=%s", PRELOAD_LIB_LOCATION);
putenv (env_string);
vector <string> words = split (cmd_line);
const char *filename = words[0].c_str();
const char *args[words.size()];
for (int i = 1; i < words.size(); ++i)
args[i - 1] = words[i].c_str();
args[words.size() - 1] = 0;
execvp (filename, (char *const *)args);
}
| |
Jesper Toft (13-01-2002)
| Kommentar Fra : Jesper Toft |
Dato : 13-01-02 01:09 |
|
Soeren Sandmann wrote:
> Jeg har lige skrevet nedenstående funktion, men jeg er ikke tilfreds
> med at jeg er nødt til caste til (char *const *) for at oversætteren
> vil acceptere det.
>
> Hvad er forskellen på const char * og char *const *?
(en *?)
At det ikke er arrayet men stringene der er const.
const pointer til pointer
og
pointer til const pointer.
/Jesper
| |
Soeren Sandmann (13-01-2002)
| Kommentar Fra : Soeren Sandmann |
Dato : 13-01-02 19:33 |
|
Jesper Toft <jesper@liscom.dk> writes:
> > Hvad er forskellen på const char * og char *const *?
> At det ikke er arrayet men stringene der er const.
>
> const pointer til pointer
> og
> pointer til const pointer.
Hmm, jeg stillede det forkerte spørgsmål. Funktionen execvp() er
erklæret sådan:
extern "C" {
int execvp (const char *file, char *const argv[]);
};
Jeg vil gerne ud fra en vector <string> konstruere et array som kan
bruges som andet argument til den funktion.
Hvordan gør jeg det bedst?
Mit forslag, som benytter sig af et cast, er dette:
vector <string> words = split (cmd_line);
const char *filename = words[0].c_str();
const char *args[words.size()];
for (unsigned int i = 1; i < words.size(); ++i)
args[i - 1] = words[i].c_str();
args[words.size() - 1] = 0;
execvp (filename, (char *const *)args);
[hvor split() deler en streng op i ord som er adskilt af blanktegn].
Er problemet i virkeligheden at execvp()'s erklæring ikke er korrekt?
Ville dette:
extern "C" {
int execvp (const char *file, const char *const argv[]);
};
have været bedre?
| |
Anders Melchiorsen (14-01-2002)
| Kommentar Fra : Anders Melchiorsen |
Dato : 14-01-02 13:54 |
|
Soeren Sandmann <sandmann@daimi.au.dk> skrev den 13-Jan-02:
> Er problemet i virkeligheden at execvp()'s erklæring ikke er korrekt?
> Ville dette:
>
> extern "C" {
> int execvp (const char *file, const char *const argv[]);
> };
>
> have været bedre?
Det var hvad jeg nåede frem til sidst jeg så på det, men jeg turde
ikke sige noget, da jeg altid bliver lidt nervøs når mere end et
niveau pointere blandes med const .
Som det er nu, lægger erklæringen op til, at execvp() ændrer på
indholdet af *argv, og det har jeg svært ved at tro, da man så ikke
kan bruge streng-konstanter.
Jeg havde egentlig håbet, at Igor ville svare på dit spørgsmål, så jeg
slap for at gætte ;).
Anders.
PS. For dem, som ikke kender cdecl, kan det bruges til at skabe
forståelse af den slags udtryk, hvis man ikke er så ferm til
const-reglerne:
cdecl> explain const char* const argv[]
declare argv as array of const pointer to const char
cdecl> explain char* const argv[]
declare argv as array of const pointer to char
| |
Richard Flamsholt (15-01-2002)
| Kommentar Fra : Richard Flamsholt |
Dato : 15-01-02 00:06 |
|
Anders Melchiorsen <anders@kalibalik.dk> skrev:
>Som det er nu, lægger erklæringen op til, at execvp() ændrer på
>indholdet af *argv, og det har jeg svært ved at tro, da man så ikke
>kan bruge streng-konstanter.
Tænk på, at parametrene til execvp() bliver givet til den nye process'
main() funktion. Den forventer jo netop en "char *argv[]", dvs et array
af modificer-bare strenge.
--
Richard Flamsholt
richard@flamsholt.dk - www.richard.flamsholt.dk
| |
Anders Melchiorsen (15-01-2002)
| Kommentar Fra : Anders Melchiorsen |
Dato : 15-01-02 10:14 |
|
Richard Flamsholt <richard@flamsholt.dk> skrev:
> Anders Melchiorsen <anders@kalibalik.dk> skrev:
> >Som det er nu, lægger erklæringen op til, at execvp() ændrer på
> >indholdet af *argv, og det har jeg svært ved at tro, da man så ikke
> >kan bruge streng-konstanter.
>
> Tænk på, at parametrene til execvp() bliver givet til den nye process'
> main() funktion. Den forventer jo netop en "char *argv[]", dvs et array
> af modificer-bare strenge.
Hvorfor godtager execlp() så en liste af konstante strenge? Og main()
forventer ikke at pegerne selv er konstante, så med din forklaring har
execvp() et "const" for meget.
Jeg vil endvidere mene, at der under alle omstændigheder sker en
kopiering, inden man når så vidt som til main() i næste program.
Ellers kan hukommelseshåndteringen jo ikke frigive den gamle proces'
hukommelse.
Nej. Det giver (indtil videre; god forklaring søges stadig) kun mening
for mig, hvis der simpelthen er glemt et const i execv*() varianterne.
Er emnet virkelig ikke beskrevet noget sted? Jeg havde ikke selv held
med at finde en forklaring ved et hurtigt kig i "Advanced Programm...".
Anders.
--
Postbud - postbud
med den røde jakke,
ring på min dør nu
og bring mig en pakke,
en pakke der kan snakke
når jeg føler mig forladt,
en pakke med en rød lille
postkassekat!
| |
Richard Flamsholt (16-01-2002)
| Kommentar Fra : Richard Flamsholt |
Dato : 16-01-02 01:57 |
|
Anders Melchiorsen <anders@kalibalik.dk> skrev:
>Hvorfor godtager execlp() så en liste af konstante strenge?
Hmm. Jeg blev snydt. Eftersom execv*() ikke er en standard C funktion
(men defineret i Posix) slog jeg op i Harbison & Steele 3rd, hvor den af
alle steder netop ikke var deklareret med const'er.
Ifølge Posix har du ret - ja, execv*() bør tage const strenge.
>Jeg vil endvidere mene, at der under alle omstændigheder sker en
>kopiering, inden man når så vidt som til main() i næste program.
Ja. Hvis vi taler Unix, så vil man efter fork() have to identiske
processer (hvor const-ness netop *bliver* arvet), men når execv() kaldes
vil den skulle kopiere sine argumenter hen til en midlertidig plads, så
programloaderen bagefter kan finde dem og fordre dem til main.
--
Richard Flamsholt
richard@flamsholt.dk - www.richard.flamsholt.dk
| |
Per Abrahamsen (14-01-2002)
| Kommentar Fra : Per Abrahamsen |
Dato : 14-01-02 13:38 |
|
Soeren Sandmann <sandmann@daimi.au.dk> writes:
> Er problemet i virkeligheden at execvp()'s erklæring ikke er korrekt?
Korrekt og korrekt... Den lover ikke at den vil undlade at lave om på
strengene. Man skal holde hvad man lover, men der er ingen regler der
siger man også skal love hvad man holder.
Du kalder den så med en array af strenge der ikke må laves om, og det
går selvfølgelig ikke da den ikke har lovet at lade dem være. Enten
må den give flere løfter, eller også må du give færre, f.eks. ved at
skrive:
char *args[words.size()];
i stedet for
const char *args[words.size()];
Hvad der er pænest afhænger af hvem der kontrolerer execvp. Hvis det
var din egen funktion kunne du ændre dens signatur, men nu er det en
standard funktion, og så bør du indrette dig efter det.
Jeg vil ikke anbefale brugen af const casts, men hvis du vælger den
løsning så brug const_cast i stedet for et gammeldags cast.
| |
Ivan Johansen (14-01-2002)
| Kommentar Fra : Ivan Johansen |
Dato : 14-01-02 17:30 |
|
Per Abrahamsen wrote:
> Soeren Sandmann <sandmann@daimi.au.dk> writes:
> Du kalder den så med en array af strenge der ikke må laves om, og det
> går selvfølgelig ikke da den ikke har lovet at lade dem være. Enten
> må den give flere løfter, eller også må du give færre, f.eks. ved at
> skrive:
>
> char *args[words.size()];
Nu er problemet bare at string::c_str() returnerer const char*, som ikke
kan gemmes i ovenstående. Så entens skal der bruges et const_cast eller
også skal der laves en kopi strengene.
> const char *args[words.size()];
Det undrer mig for øvrigt at dette kan kompileres, da words.size() ikke
er en konstant. Jeg ved dog godt at der findes kompilere som godtager
det alligevel, men det er ikke gyldigt C++, og min compiler godtager det
ikke.
Ivan Johansen
| |
Soeren Sandmann (14-01-2002)
| Kommentar Fra : Soeren Sandmann |
Dato : 14-01-02 17:57 |
|
Ivan Johansen <NG@Padowan.dk> writes:
> Det undrer mig for øvrigt at dette kan kompileres, da words.size()
> ikke er en konstant. Jeg ved dog godt at der findes kompilere som
> godtager det alligevel, men det er ikke gyldigt C++, og min compiler
> godtager det ikke.
G++ godtager det heller ikke med -pedantic (som jeg nu vil begynde at
bruge). Jeg kan desværre ikke bruge -ansi, for så bliver alt muligt
som jeg har brug for, slået fra i systemets header-filer.
Koden ser nu sådan ud:
vector <string> words = split (cmd_line);
const char *filename = words[0].c_str();
char **args = new char *[words.size()];
for (unsigned int i = 1; i < words.size(); ++i)
args[i - 1] = strdup (words[i].c_str());
args[words.size() - 1] = 0;
execvp (filename, args);
| |
Anders Melchiorsen (28-01-2002)
| Kommentar Fra : Anders Melchiorsen |
Dato : 28-01-02 23:03 |
|
Soeren Sandmann <sandmann@daimi.au.dk> skrev den 14-Jan-02:
> Koden ser nu sådan ud:
>
> vector <string> words = split (cmd_line);
>
> const char *filename = words[0].c_str();
>
> char **args = new char *[words.size()];
> for (unsigned int i = 1; i < words.size(); ++i)
> args[i - 1] = strdup (words[i].c_str());
>
> args[words.size() - 1] = 0;
>
> execvp (filename, args);
Er det ikke således, at "args[0]" skal indeholde hvad der bliver til
"argv[0]", altså stort set "filename" ?
Jeg vil mene, at din args[] er én for lille, idet du burde indskyde
words[0] forrest.
Ja?
Anders.
--
Lirum i Virum
og Larum i Farum
tog fra Nærum
med fru Lærum
for at købe smør
i Smørum.
| |
Per Abrahamsen (15-01-2002)
| Kommentar Fra : Per Abrahamsen |
Dato : 15-01-02 13:02 |
|
Ivan Johansen <NG@Padowan.dk> writes:
> Per Abrahamsen wrote:
>
> > const char *args[words.size()];
>
> Det undrer mig for øvrigt at dette kan kompileres, da words.size()
> ikke er en konstant. Jeg ved dog godt at der findes kompilere som
> godtager det alligevel, men det er ikke gyldigt C++, og min compiler
> godtager det ikke.
Det er en GNU udvidelse. Den er muligvis med i C99, i så fald synes
jeg det er ok at brue den i C++, da den nok i så fald vil komme medi
næste version af standarden.
C99 har en variant af fleksible arrays, men jeg ved ikke om det er som
ovenfor (status for support i GCC 3.0 er beskevet som "broken").
| |
|
|