|
| Simpelt string-problem Fra : Peter Brixen |
Dato : 03-01-03 13:47 |
|
Jeg er lige ved at bakse med noget C, og jeg har et problem, som
egentlig burde være nemt nok at løse. Jeg har variablen
char* str1 = "/dir/dir/dir";
Hvordan kan jeg slette det sidste stykke ned til /, altså måske med
andre ord, hvordan får jeg kopieret "/dir/dir"?
-- Peter.
| |
Igor V. Rafienko (03-01-2003)
| Kommentar Fra : Igor V. Rafienko |
Dato : 03-01-03 14:24 |
|
[ Peter Brixen ]
[ ... ]
> char* str1 = "/dir/dir/dir";
Uff, uff! Du mener sikkert
char str1[] = "/dir/dir/dir";
> Hvordan kan jeg slette det sidste stykke ned til /, altså måske med
> andre ord, hvordan får jeg kopieret "/dir/dir"?
Hva inneholder teksten du skal plukke kataloger ut ifra? (husk fx. at
"//foo" er det samme som "/foo" for en rekke systemkall. Er det noen
andre patologiske tilfeller som kan oppstå?)
Akkurat det med å "slette" blir litt klønete av flere grunner. En
veldig vanlig strategi er å skrive '\0' der man vil at strengen skal
(logisk sett) slutte. Et veldig stort antall systemkall og
biblioteksfunksjoner antar at '\0' betegner nettopp slutten på
teksten.
Da var det bare å finne hvor teksten skulle slutte. Ta en titt på
strchr, strrchr, strcspn, strspn funksjonene. Når du har funnet
hvilken del av den opprinnelige teksten du er interessert i, kan du
enten kopiere den delen som interesserer deg (fx. vha. memmove) eller,
slik jeg antydet, skrive '\0'-byte i den aktuelle posisjonen.
(Og nei, du får ikke en linje kode før du demonstrerer at du har
forsøkt å løse problemet selv)
ivr
--
<peder> igorr: tcl ja... det er fra de dypeste avgrunnene i helvete det...
<peder> php er bare fra foajeen
-- pederst på irc
| |
Helge Jensen (04-01-2003)
| Kommentar Fra : Helge Jensen |
Dato : 04-01-03 00:23 |
|
Igor V. Rafienko wrote:
> [ Peter Brixen ]
>
> [ ... ]
>
>
>> char* str1 = "/dir/dir/dir";
>
>
>
> Uff, uff! Du mener sikkert
>
> char str1[] = "/dir/dir/dir";
Hvad skulle det hjælpe?
Jeg foretrækker:
const char * const str1 = "foo";
Hvis jeg ikke skal bruge str1 til at pege på noget andet,
const char * str1 = "foo";
ellers
--
Helge
| |
Mads Orbesen Troest (04-01-2003)
| Kommentar Fra : Mads Orbesen Troest |
Dato : 04-01-03 00:55 |
|
>>> char* str1 = "/dir/dir/dir";
>> Uff, uff! Du mener sikkert
>> char str1[] = "/dir/dir/dir";
>Hvad skulle det hjælpe?
Dermed er han garanteret, at strengen /ikke/ er allokeret i read-only
memory, og kan derfor frit modificere den (fx indskrive et terminerende \0
der hvor han ønsker den skal slutte) uden at segmentation faile, fordi
compileren ellers er i sin gode ret til at allokere strengen i et const
segment.
/\/\\ads Orbesen Troest
| |
Kim Hansen (04-01-2003)
| Kommentar Fra : Kim Hansen |
Dato : 04-01-03 02:25 |
|
"Mads Orbesen Troest" <mads@troest.NEVERMORE.dk> writes:
> >>> char* str1 = "/dir/dir/dir";
> >> Uff, uff! Du mener sikkert
> >> char str1[] = "/dir/dir/dir";
> >Hvad skulle det hjælpe?
>
> Dermed er han garanteret, at strengen /ikke/ er allokeret i read-only
> memory, og kan derfor frit modificere den (fx indskrive et terminerende \0
> der hvor han ønsker den skal slutte) uden at segmentation faile, fordi
> compileren ellers er i sin gode ret til at allokere strengen i et const
> segment.
Jeg sad forleden dag og kunne huske at der var en forskel, men jeg
kunne ikke huske om man skulle bruge *s eller s[] for at kunne rette i
strengen.
1. Er der en nem/logisk måde at indse at det er *s der er immutable.
2. Hvor kan det slås op? Står det i 'The C Programming Language'?
--
Kim Hansen | |\ _,,,---,,_ | Det er ikke
Dalslandsgade 8, A708 | /,`.-'`' -. ;-;;,_ | Jeopardy.
2300 København S | |,4- ) )-,_. ,\ ( `'-' | Svar _efter_
Phone: 32 88 60 86 | '---''(_/--' `-'\_) | spørgsmålet.
| |
Kent Friis (04-01-2003)
| Kommentar Fra : Kent Friis |
Dato : 04-01-03 10:38 |
|
Den 04 Jan 2003 02:25:18 +0100 skrev Kim Hansen:
>"Mads Orbesen Troest" <mads@troest.NEVERMORE.dk> writes:
>
>> >>> char* str1 = "/dir/dir/dir";
>> >> Uff, uff! Du mener sikkert
>> >> char str1[] = "/dir/dir/dir";
>> >Hvad skulle det hjælpe?
>>
>> Dermed er han garanteret, at strengen /ikke/ er allokeret i read-only
>> memory, og kan derfor frit modificere den (fx indskrive et terminerende \0
>> der hvor han ønsker den skal slutte) uden at segmentation faile, fordi
>> compileren ellers er i sin gode ret til at allokere strengen i et const
>> segment.
>
>Jeg sad forleden dag og kunne huske at der var en forskel, men jeg
>kunne ikke huske om man skulle bruge *s eller s[] for at kunne rette i
>strengen.
>
>1. Er der en nem/logisk måde at indse at det er *s der er immutable.
s[] er et array der indeholder "/dir/dir/dir".
*s er en pointer til den streng du har skrevet i source-filen, og som
alt andet du har skrevet i source-filen kan det normalt ikke ændres
(fx kan du heller ikke runtime ændre indholdet af main() - medmindre
du begynder på selv-modificerende kode).
Mvh
Kent
--
You haven't seen _multitasking_ until you've seen Railroad
Tycoon II and Unreal Tournament run side by side
| |
Ukendt (04-01-2003)
| Kommentar Fra : Ukendt |
Dato : 04-01-03 14:22 |
|
Kent Friis wrote:
> Den 04 Jan 2003 02:25:18 +0100 skrev Kim Hansen:
>
>>"Mads Orbesen Troest" <mads@troest.NEVERMORE.dk> writes:
>>
>>
>>>>>> char* str1 = "/dir/dir/dir";
>>>>>
>>>>>Uff, uff! Du mener sikkert
>>>>>char str1[] = "/dir/dir/dir";
>>>>
>>>>Hvad skulle det hjælpe?
>>>
>>>Dermed er han garanteret, at strengen /ikke/ er allokeret i read-only
>>>memory, og kan derfor frit modificere den (fx indskrive et terminerende \0
>>>der hvor han ønsker den skal slutte) uden at segmentation faile, fordi
>>>compileren ellers er i sin gode ret til at allokere strengen i et const
>>>segment.
>>
>>Jeg sad forleden dag og kunne huske at der var en forskel, men jeg
>>kunne ikke huske om man skulle bruge *s eller s[] for at kunne rette i
>>strengen.
>>
>>1. Er der en nem/logisk måde at indse at det er *s der er immutable.
>
>
> s[] er et array der indeholder "/dir/dir/dir".
>
> *s er en pointer til den streng du har skrevet i source-filen, og som
> alt andet du har skrevet i source-filen kan det normalt ikke ændres
> (fx kan du heller ikke runtime ændre indholdet af main() - medmindre
> du begynder på selv-modificerende kode).
>
> Mvh
> Kent
Hvad med noget ligende:
char str1[] = "/dir/dir/dir";
char* index;
char oldch;
if( (index = strrchr( str1, '/' )) != 0 ) {
oldch = index[0];
index[0] = '\0';
strcpy( <new string>, str1 );
index[0] = oldch;
}
bare et forslag....
Cheers, Frank
| |
Igor V. Rafienko (04-01-2003)
| Kommentar Fra : Igor V. Rafienko |
Dato : 04-01-03 15:55 |
|
[ Kim Hansen ]
[ ... ]
> 2. Hvor kan det slås op? Står det i 'The C Programming Language'?
Slike ting slåes alltid opp i standarden.
Det er tre ting som er interessante her:
* Typen til en string literal
* Semantikken til en char-array definisjon og initialisering
* Semantikken til en char-peker definisjon og initialisering
Jeg har dessverre ikke C standarden (hverken C90 eller C99), men jeg
er temmelig sikker på at typen til en string literal er "array of N
const char" (selv om N869[*] sier noe _helt_ annet i 6.4.5, p 5, noe
som strider mot 6.7.8, p 32 (Example 8) -- jeg skjønner hvorfor dette
er "committee draft"). Array-initialisering skjer ved å ta en kopi av
elementene i det initialiserende uttrykket (N869 6.7.8).
Peker-initialisering derimot betyr at pekeren får en adresse som
stammer fra det initialiserende uttrykket (også fra 6.7.8 og 6.5.16);
det tas ingen kopi av objektet (det er slik en array konverteres til
en peker).
Tilsvarende resonnement holder for C++ (jeg er for lat til å slå opp
paragrafnumrene).
K&R2 inneholder vel også forklaringer rundt dette 5.5 forklarer det
meste man trenger å vite.
ivr
--
<peder> igorr: tcl ja... det er fra de dypeste avgrunnene i helvete det...
<peder> php er bare fra foajeen
-- pederst på irc
| |
Kim Hansen (04-01-2003)
| Kommentar Fra : Kim Hansen |
Dato : 04-01-03 16:17 |
|
igorr@ifi.uio.no (Igor V. Rafienko) writes:
> [ Kim Hansen ]
>
> > 2. Hvor kan det slås op? Står det i 'The C Programming Language'?
>
> Slike ting slåes alltid opp i standarden.
Jeg har kun K&R2, så jeg må nøjes med hvad jeg kan finde der...
[snip]
> K&R2 inneholder vel også forklaringer rundt dette 5.5 forklarer det
> meste man trenger å vite.
Tak, der er jo en fin og grundig forklaring. Jeg har åbenbart bare
kigget på de forkerte sider i bogen.
--
Kim Hansen | |\ _,,,---,,_ | Det er ikke
Dalslandsgade 8, A708 | /,`.-'`' -. ;-;;,_ | Jeopardy.
2300 København S | |,4- ) )-,_. ,\ ( `'-' | Svar _efter_
Phone: 32 88 60 86 | '---''(_/--' `-'\_) | spørgsmålet.
| |
Martin Moller Peders~ (03-01-2003)
| Kommentar Fra : Martin Moller Peders~ |
Dato : 03-01-03 14:38 |
|
In <3E158646.9DA2E97@jyde.dk> Peter Brixen <brixen@jyde.dk> writes:
>Jeg er lige ved at bakse med noget C, og jeg har et problem, som
>egentlig burde være nemt nok at løse. Jeg har variablen
> char* str1 = "/dir/dir/dir";
>Hvordan kan jeg slette det sidste stykke ned til /, altså måske med
>andre ord, hvordan får jeg kopieret "/dir/dir"?
well, kommer lidt an paa hvordan du skal bruge str1 bagefter, men
du kan f.x. skrive:
char *str1="/dir/dir/dir";
int finish=0;
char *p;
for (p=str1+strlen(str1)-1; !finish; p--) {
if (p==str1)
finish=1
if (*p='/') {
finish=1;
*p='\0';
}
}
| |
Igor V. Rafienko (03-01-2003)
| Kommentar Fra : Igor V. Rafienko |
Dato : 03-01-03 14:42 |
|
[ Martin Moller Pedersen ]
[ ... ]
> well, kommer lidt an paa hvordan du skal bruge str1 bagefter, men du
> kan f.x. skrive:
Neppe:
$ /local/snacks/bin/gcc stringtest.c
$ ./a.out
Segmentation Fault
$
ivr
--
<peder> igorr: tcl ja... det er fra de dypeste avgrunnene i helvete det...
<peder> php er bare fra foajeen
-- pederst på irc
| |
John Ekblom (03-01-2003)
| Kommentar Fra : John Ekblom |
Dato : 03-01-03 22:20 |
|
Put en nulafslutter ind hvor du vil have din streng afsluttet:
str1[8]= 0;
------------------------------------------
Med venlig hilsen
Comet Computer ApS
John Ekblom
Tlf.: 70 25 12 13
www.cometcomputer.dk
"Peter Brixen" <brixen@jyde.dk> skrev i en meddelelse
news:3E158646.9DA2E97@jyde.dk...
> Jeg er lige ved at bakse med noget C, og jeg har et problem, som
> egentlig burde være nemt nok at løse. Jeg har variablen
>
> char* str1 = "/dir/dir/dir";
>
> Hvordan kan jeg slette det sidste stykke ned til /, altså måske med
> andre ord, hvordan får jeg kopieret "/dir/dir"?
>
> -- Peter.
>
| |
Helge Jensen (04-01-2003)
| Kommentar Fra : Helge Jensen |
Dato : 04-01-03 00:20 |
|
John Ekblom wrote:
> Put en nulafslutter ind hvor du vil have din streng afsluttet:
>
> str1[8]= 0;
Det kan man ikke. Streng-konstanter kan være immutable.
Som en undtagelse fra standarden har compileren lov til at allokere
streng konstanter i ikke skrivbar memory, og assigne dem til non-const
char *. god kode er som regel:
const char * my_str = "foo";
En forslag til god implementation ville være (ukompileret, utestet kode):
char *dirname(const char * const path) {
/* get back to last '/' */
const char *last_slash = strrchr(path, '/');
/* was there even any? */
if ( last_slash == NULL )
return strdup(path);
/* rewind until no slash or beginnig of string */
while ( last_slash > path && *(last_slash-1) == '/' )
--last_slash;
/* path is entirely '/'s? */
if ( last_slash == path )
return strdup("/");
/* copy preceeding part */
{
size_t len = (last_slash - path);
char *ret = malloc(len + 1);
if ( ret == NULL )
return NULL;
strncpy(ret, path, len);
ret[len] = '\0x0';
return ret;
}
}
--
Helge
| |
Peter Brixen (04-01-2003)
| Kommentar Fra : Peter Brixen |
Dato : 04-01-03 18:51 |
|
Helge Jensen wrote:
> En forslag til god implementation ville være (ukompileret, utestet kode):
>
> char *dirname(const char * const path) {
> /* get back to last '/' */
> const char *last_slash = strrchr(path, '/');
> /* was there even any? */
> if ( last_slash == NULL )
> return strdup(path);
> /* rewind until no slash or beginnig of string */
> while ( last_slash > path && *(last_slash-1) == '/' )
> --last_slash;
> /* path is entirely '/'s? */
> if ( last_slash == path )
> return strdup("/");
> /* copy preceeding part */
> {
> size_t len = (last_slash - path);
> char *ret = malloc(len + 1);
> if ( ret == NULL )
> return NULL;
> strncpy(ret, path, len);
> ret[len] = '\0x0';
> return ret;
> }
> }
>
Det virker, undtagen at '\0x0' skal være '\0'. Nu har jeg da lært noget mere
om strings i C, og det er der åbenbart flere, der har, så det er vel en god
ting.
Jeg takker for svarene.
-- Peter.
| |
John Ekblom (08-01-2003)
| Kommentar Fra : John Ekblom |
Dato : 08-01-03 20:01 |
|
Hej Helge,
Det er muligt at jeg/du har misforstået spørgsmålet, eller at jeg blot ikke
fatter pointen i dit svar, men:
char* str1 = "/dir/dir/dir";
str1[8]= 0;
printf("%s",str1);
giver output'et: /dir/dir
Så det kan man altså godt - eller har jeg misforstået dig ?
------------------------------------------
Med venlig hilsen
Comet Computer ApS
John Ekblom
Tlf.: 70 25 12 13
www.cometcomputer.dk
"Helge Jensen" <j_e_n_s_e_n@s_l_o_g.d_k> skrev i en meddelelse
news:3e161a90$0$210$edfadb0f@dread12.news.tele.dk...
John Ekblom wrote:
> Put en nulafslutter ind hvor du vil have din streng afsluttet:
>
> str1[8]= 0;
Det kan man ikke. Streng-konstanter kan være immutable.
Som en undtagelse fra standarden har compileren lov til at allokere
streng konstanter i ikke skrivbar memory, og assigne dem til non-const
char *. god kode er som regel:
const char * my_str = "foo";
En forslag til god implementation ville være (ukompileret, utestet kode):
char *dirname(const char * const path) {
/* get back to last '/' */
const char *last_slash = strrchr(path, '/');
/* was there even any? */
if ( last_slash == NULL )
return strdup(path);
/* rewind until no slash or beginnig of string */
while ( last_slash > path && *(last_slash-1) == '/' )
--last_slash;
/* path is entirely '/'s? */
if ( last_slash == path )
return strdup("/");
/* copy preceeding part */
{
size_t len = (last_slash - path);
char *ret = malloc(len + 1);
if ( ret == NULL )
return NULL;
strncpy(ret, path, len);
ret[len] = '\0x0';
return ret;
}
}
--
Helge
| |
Helge Jensen (08-01-2003)
| Kommentar Fra : Helge Jensen |
Dato : 08-01-03 20:50 |
|
John Ekblom wrote:
> Hej Helge,
>
> Det er muligt at jeg/du har misforstået spørgsmålet, eller at jeg blot ikke
> fatter pointen i dit svar,
tjo, det er jo mere subtilt end man lige tror.
> char* str1 = "/dir/dir/dir";
> str1[8]= 0;
> printf("%s",str1);
>
> giver output'et: /dir/dir
>
> Så det kan man altså godt - eller har jeg misforstået dig ?
Det kan man godt sige. ANSI-C (og C99) siger, at dit program har
udefineret opførsel, fordi du ændrer en streng konstant (den str1 peger
på).
Det er rent held (eller uheld om man vil) at koden "virker" med din
compiler, men jeg kan garantere dig, at det ikke virker med GCC på linux
eller win32 (giver SIGSEGV), og compileren er i sin gode ret til at give
dit program lige præcis den semantik den vil, da din kode har udefineret
semantik.
grunden til, at du overhovedet kan skrive:
char *str1 = "xxx";
er, at der er en eksplicit undtagelse fra const-reglerne, for at kode
fra før "const" blev indført stadig skulle compile. Det burde være
krævet at du skrev:
const char *str1 = "xxx"; /* en pointer til en konstanten "xxx" */
eller evt.
char str1[] = "xxx"; /* en lokal-kopi af konstanten "xxx" */
Du kan evt. gøre:
char *str1 = strdup("xxx"); /* en heap-kopi af konstanten "xxx" */
Hvis du gerne vil have en global streng man kan ændre på.
Det er iøvrigt god skik (et idiom) at skrive:
const char *x = "xxx";
For så kan compileren advare om, at f.eks.
x[1] = 'x';
er ulovligt.
--
Helge
| |
John Ekblom (15-01-2003)
| Kommentar Fra : John Ekblom |
Dato : 15-01-03 20:16 |
|
Hej Helge,
Ikke destro mindre virker det altså også under Win32.
Se nedenstående uddrag til Borland C++ Builder.
void __fastcall TForm1::FormCreate(TObject *Sender)
{
char* str1 = "/dir/dir/dir";
str1[8]= 0;
Caption= str1;
}
Resultatet er "/dir/dir".
Jeg har ikke en LINUX compiler ved hånden, men har tidligere anvendt samme
teknik under UNIX - uden problemer.
Hvorfor skulle str1 iøvrigt være at betragte som en Const ?
------------------------------------------
Med venlig hilsen
Comet Computer ApS
John Ekblom
Tlf.: 70 25 12 13
www.cometcomputer.dk
| |
Anders Wegge Jakobse~ (15-01-2003)
| Kommentar Fra : Anders Wegge Jakobse~ |
Dato : 15-01-03 20:47 |
|
"John" == John Ekblom <ekblom@image.dk> writes:
> Hej Helge,
> Ikke destro mindre virker det altså også under Win32.
> Se nedenstående uddrag til Borland C++ Builder.
Ja, og hvis man er heldig nok, kan man også montere hunstikket på en
forlængerledning mens der er spænding på.
[Nasale dæmoner]
> Resultatet er "/dir/dir".
Ja, men hvis du kører det samme stykke kode på den deathstar-9000,
jeg normalt benytter som hjemmemaskine, udløser den et atomangreb på
Bagsværd og omegn.
> Jeg har ikke en LINUX compiler ved hånden, men har tidligere anvendt samme
> teknik under UNIX - uden problemer.
> Hvorfor skulle str1 iøvrigt være at betragte som en Const ?
Fordi det er sådan C-99 definerer strenge.
--
/Wegge
| |
John Ekblom (15-01-2003)
| Kommentar Fra : John Ekblom |
Dato : 15-01-03 21:55 |
|
> Ja, og hvis man er heldig nok, kan man også montere hunstikket på en
> forlængerledning mens der er spænding på.
>
> [Nasale dæmoner]
>
Ja, jeg må være født under en meget meget heldig stjerne.
Men når man skriver: "men jeg kan garantere dig, at det ikke virker med GCC
på linux
eller win32 (giver SIGSEGV)" - så må det naturligvis prøves ...
| |
Anders Wegge Jakobse~ (15-01-2003)
| Kommentar Fra : Anders Wegge Jakobse~ |
Dato : 15-01-03 22:52 |
|
"John" == John Ekblom <ekblom@image.dk> writes:
>> Ja, og hvis man er heldig nok, kan man også montere hunstikket på en
>> forlængerledning mens der er spænding på.
>>
>> [Nasale dæmoner]
>>
> Ja, jeg må være født under en meget meget heldig stjerne.
> Men når man skriver: "men jeg kan garantere dig, at det ikke virker med GCC
> på linux
> eller win32 (giver SIGSEGV)" - så må det naturligvis prøves ...
Det virker ikke for mig. Har du tilfældigvis brugt
-fwriteable-strings som argument til din GCC? Hvis ikke må du gerne
købe et par lottokuponer for mig.
--
/Wegge
| |
John Ekblom (18-01-2003)
| Kommentar Fra : John Ekblom |
Dato : 18-01-03 02:46 |
|
> Det virker ikke for mig. Har du tilfældigvis brugt
> -fwriteable-strings som argument til din GCC? Hvis ikke må du gerne
> købe et par lottokuponer for mig.
Som jeg skrev har jeg ikke en LINUX compiler tilrådighed.
Programstumpen var til Borland C++ Builder (win32).
| |
Martin Moller Peders~ (18-01-2003)
| Kommentar Fra : Martin Moller Peders~ |
Dato : 18-01-03 15:21 |
|
In <zx2W9.38857$Hl6.4596525@news010.worldonline.dk> "John Ekblom" <ekblom@image.dk> writes:
>> Det virker ikke for mig. Har du tilfældigvis brugt
>> -fwriteable-strings som argument til din GCC? Hvis ikke må du gerne
>> købe et par lottokuponer for mig.
>Som jeg skrev har jeg ikke en LINUX compiler tilrådighed.
>Programstumpen var til Borland C++ Builder (win32).
GCC er ikke en LINUX compiler.
/Martin
| |
John Ekblom (18-01-2003)
| Kommentar Fra : John Ekblom |
Dato : 18-01-03 16:27 |
|
> GCC er ikke en LINUX compiler.
Nå, det tog jeg for givet.
Hvilken C-compiler er det så ?
| |
N/A (18-01-2003)
| Kommentar Fra : N/A |
Dato : 18-01-03 17:49 |
|
| |
Martin Moller Peders~ (18-01-2003)
| Kommentar Fra : Martin Moller Peders~ |
Dato : 18-01-03 17:49 |
|
In <izeW9.39057$Hl6.4654017@news010.worldonline.dk> "John Ekblom" <ekblom@image.dk> writes:
>> GCC er ikke en LINUX compiler.
>Nå, det tog jeg for givet.
>Hvilken C-compiler er det så ?
GCC er navnet paa compileren og den findes til flere platforme end de fleste
mennesker overhovedet kender.
/Martin
| |
Mogens Hansen (16-01-2003)
| Kommentar Fra : Mogens Hansen |
Dato : 16-01-03 06:47 |
|
"John Ekblom" <ekblom@image.dk>
[8<8<8<]
> Hvorfor skulle str1 iøvrigt være at betragte som en Const ?
F.eks. fordi så er det tilladeligt for et compiler system til et embedded
system at lægge strengen i ROM (hvor den under alle omstændigheder skal
ligge) i stedet for i RAM, og derved spare på RAM'en og undgå en kopiering
(under opstart).
Venlig hilsen
Mogens Hansen
| |
John Ekblom (18-01-2003)
| Kommentar Fra : John Ekblom |
Dato : 18-01-03 03:13 |
|
> F.eks. fordi så er det tilladeligt for et compiler system til et embedded
> system at lægge strengen i ROM (hvor den under alle omstændigheder skal
> ligge) i stedet for i RAM, og derved spare på RAM'en og undgå en kopiering
> (under opstart).
Ja, men jeg ville have forventet at:
A.
const char* str1="/dir/dir/dir";
Gav en konstant streng.
Og at
B.
char* str1 = "/dir/dir/dir";
Gav en variabel streng.
Men sådan kan jeg nu forstå det ikke er iflg. C99 !!!?
Nymodens pjat og pjank - sådan var det ikke i halvfemserne !!!
Hvorfor hulen skulle det være så svært at skrive "const" foran de variable
man gerne ville lave konstante, at man har indført nye regler her.
| |
Mogens Hansen (18-01-2003)
| Kommentar Fra : Mogens Hansen |
Dato : 18-01-03 10:35 |
|
"John Ekblom" <ekblom@image.dk> wrote
> Men sådan kan jeg nu forstå det ikke er iflg. C99 !!!?
> Nymodens pjat og pjank - sådan var det ikke i halvfemserne !!!
Er du sikker ?
> Hvorfor hulen skulle det være så svært at skrive "const" foran de variable
> man gerne ville lave konstante, at man har indført nye regler her.
Det er anbefalet (men desværre ikke påkrævet) altid at skrive at skrive
"const char*".
Hvad får dig til at tro at der er indført nye regler på det punkt ?
(Hint: det er der _ikke_ - tværtimod det er en _gammel_ regel)
Venlig hilsen
Mogens Hansen
| |
John Ekblom (18-01-2003)
| Kommentar Fra : John Ekblom |
Dato : 18-01-03 16:18 |
|
> > Hvorfor hulen skulle det være så svært at skrive "const" foran de
variable
> > man gerne ville lave konstante, at man har indført nye regler her.
Det er således jeg forstår indlæggende her fra gruppen.
Er det da ikke noget der først er indført med C99 ?
Hvorfor skulle det i øvrigt ellers give en forskel at man bruger
"optionen -traditional." (Se indlæg fra Jesper Wolf Jespersen)
| |
Jesper Wolf Jesperse~ (18-01-2003)
| Kommentar Fra : Jesper Wolf Jesperse~ |
Dato : 18-01-03 15:34 |
|
Hej John.
> Ikke destro mindre virker det altså også under Win32.
> Se nedenstående uddrag til Borland C++ Builder.
>
> void __fastcall TForm1::FormCreate(TObject *Sender)
> {
> char* str1 = "/dir/dir/dir";
> str1[8]= 0;
> Caption= str1;
> }
>
> Resultatet er "/dir/dir".
>
> Jeg har ikke en LINUX compiler ved hånden, men har tidligere anvendt samme
> teknik under UNIX - uden problemer.
>
> Hvorfor skulle str1 iøvrigt være at betragte som en Const ?
Det er heller ikke str1 der er konstant. str1 er en pointer til en char.
Men det hukommelses område den peger på kan være konstant, det er en
initialiseringsstreng ikke en variabel.
Hvis du gerne vil vide hvad du laver istedet for at stole på forskellige
compileres konventioner, så tag dog og afsæt lidt plads til dine strenge.
For eksempel vil denne kode virke uanset hvilken platform du bruger den på.
#include <stdio.h>
int main(int argc.char *argv[])
{
char str1 [80] = "/dir/dir/dir" ; /* her afsætter vi plads til
variablen og initialiserer den */
puts(str1);
str1 [8] = 0;
puts(str1);
}
Jeg kan ikke udtale mig om hvilke C standarder der foreskriver hvorfor en
adfærd. Jeg har bare lært at acceptere at tingene gøres forskelligt og så må
jeg skrive min kode så den slags detaljer ikke tæller.
med venlig hilsen
Jesper Wolf Jespersen
| |
John Ekblom (18-01-2003)
| Kommentar Fra : John Ekblom |
Dato : 18-01-03 16:24 |
|
> #include <stdio.h>
> int main(int argc.char *argv[])
> {
> char str1 [80] = "/dir/dir/dir" ; /* her afsætter vi plads til
> variablen og initialiserer den */
> puts(str1);
> str1 [8] = 0;
> puts(str1);
> }
>
> Jeg kan ikke udtale mig om hvilke C standarder der foreskriver hvorfor en
> adfærd. Jeg har bare lært at acceptere at tingene gøres forskelligt og så
må
> jeg skrive min kode så den slags detaljer ikke tæller.
Ja, jeg er enig.
Jeg kendte blot ikke denne adfærdsforskel før nu.
Før denne diskussion ville jeg have forsvoret at:
char *str1="/dir/dir/dir"; og
char str1[13]= "/dir/dir/dir";
ville være det samme uanset kompiler. Blot med den fordel at man i eksempel
1 ikke behøvede at tænke over antal tegn og huske at tælle nulafslutter med.
M.v.h.
John E.
| |
Mogens Hansen (18-01-2003)
| Kommentar Fra : Mogens Hansen |
Dato : 18-01-03 20:02 |
|
"John Ekblom" <ekblom@image.dk> wrote in message
news:SweW9.39054$Hl6.4653872@news010.worldonline.dk...
[8<8<8<]
> ville være det samme uanset kompiler. Blot med den fordel at man i
eksempel
> 1 ikke behøvede at tænke over antal tegn og huske at tælle nulafslutter
med.
Du kan skrive
char str1[]= "/dir/dir/dir";
så slipper du for at tælle.
Venlig hilsen
Mogens Hansen
| |
Per Abrahamsen (16-01-2003)
| Kommentar Fra : Per Abrahamsen |
Dato : 16-01-03 15:50 |
|
"John Ekblom" <ekblom@image.dk> writes:
> Jeg har ikke en LINUX compiler ved hånden, men har tidligere anvendt samme
> teknik under UNIX - uden problemer.
Her er en lille test på en Linux maskine:
goedel% cat test.c
int main ()
{
char* str1 = "/dir/dir/dir";
str1[8]= 0;
return 0;
}
goedel% gcc test.c
goedel% ./a.out
Segmentation fault
goedel%
Teknisk set sker der det at GCC lægger alle strenge i et særlig
skrivebeskyttet segment af hukommelsen ved navn ".text", samme sted
det lægger selve programmet. Det er smart af flere grunde:
- man sikrer programmet (og strengene) mod at blive overskrevet ved et uheld.
- ".text" segmentet kan lettere deles mellem flere programmer der
kører samtidig, og spare memory på den måde.
- Som Morten nævnte, man kan lægge det i ROM hvis laver embedded
devices, hvilket GCC ofte bruges til.
Fordi at der er en del, mest ældre, programmer der bruger samme teknik
som dig, så er der nogen compilere der lægger strenge i ".data"
segmentet per default, måske har du brugt en af dem.
| |
Jesper Wolf Jesperse~ (16-01-2003)
| Kommentar Fra : Jesper Wolf Jesperse~ |
Dato : 16-01-03 22:08 |
|
Hej Per.
> > Jeg har ikke en LINUX compiler ved hånden, men har tidligere anvendt
samme
> > teknik under UNIX - uden problemer.
>
> Her er en lille test på en Linux maskine:
>
> goedel% cat test.c
> int main ()
> {
> char* str1 = "/dir/dir/dir";
> str1[8]= 0;
> return 0;
> }
> goedel% gcc test.c
> goedel% ./a.out
> Segmentation fault
> goedel%
>
> - Som Morten nævnte, man kan lægge det i ROM hvis laver embedded
> devices, hvilket GCC ofte bruges til.
Han hedder nu Mogens
> Fordi at der er en del, mest ældre, programmer der bruger samme teknik
> som dig, så er der nogen compilere der lægger strenge i ".data"
> segmentet per default, måske har du brugt en af dem.
Prøv med optionen --writable-strings, så har du den adfærd du leder efter.
altså oversæt med "gcc --writable-strings test.c" og du får ingen
segmentation fault.
Hvis du vil have rigtig oldtimer adfærd kan du køre med
optionen -traditional.
Der er tonsvis af optioner til GCC, prøv for eksempel at køre gcc -v --help,
men kør det gennem en pager da der kommer ret meget output.
Eller kig i "info gcc", der er det organiseret mere fornuftigt.
Med venlig hilsen
Jesper Wolf Jespersen
| |
Per Abrahamsen (18-01-2003)
| Kommentar Fra : Per Abrahamsen |
Dato : 18-01-03 19:38 |
|
"John Ekblom" <ekblom@image.dk> writes:
> Er det da ikke noget der først er indført med C99 ?
Nej, sådan har det været siden den første C standard i 89, 10 år
tidligere.
> Hvorfor skulle det i øvrigt ellers give en forskel at man bruger
> "optionen -traditional." (Se indlæg fra Jesper Wolf Jespersen)
-traditional giver kompatibilitet med nogen populære Unix C compilere
fra før den første standard.
| |
Per Abrahamsen (18-01-2003)
| Kommentar Fra : Per Abrahamsen |
Dato : 18-01-03 19:48 |
|
"John Ekblom" <ekblom@image.dk> writes:
> Ja, men jeg ville have forventet at:
>
> A.
> const char* str1="/dir/dir/dir";
> Gav en konstant streng.
>
> Og at
>
> B.
> char* str1 = "/dir/dir/dir";
>
> Gav en variabel streng.
Det ville være stærkt imod den måde C's typesystem fungerer. Typen af
et udtryk afhænger generelt ikke af hvordan det bruges. Tænk
f.eks. på
const char* str1= malloc (50);
Eller
const char* str1= strcat ("hello ", "world");
En kontant har altid samme type i C, uanset hvor den optræder.
> Men sådan kan jeg nu forstå det ikke er iflg. C99 !!!?
> Nymodens pjat og pjank - sådan var det ikke i halvfemserne !!!
Jo det var. Men sådan var det ikke altid i 80'erne, før den første
standard (ANSI C 89). Dengang var der slet ikke noget der hed
"const", der er en ANSI opfindelse (eller rettere, et lån fra C++).
| |
Per Abrahamsen (18-01-2003)
| Kommentar Fra : Per Abrahamsen |
Dato : 18-01-03 19:52 |
|
"John Ekblom" <ekblom@image.dk> writes:
> Før denne diskussion ville jeg have forsvoret at:
>
> char *str1="/dir/dir/dir"; og
> char str1[13]= "/dir/dir/dir";
>
> ville være det samme uanset kompiler. Blot med den fordel at man i eksempel
> 1 ikke behøvede at tænke over antal tegn og huske at tælle nulafslutter med.
Skriv
char str1[] = "/dir/dir/dir";
og compileren afsætter selv den fornødne plads.
| |
|
|