warning: Unsequenced modification and access to 'j'

Fórumok

Na, de miért?

while (isupper((unsigned char) p[j])) buff[j++] = p[j];

Az '=' operátor right to left asszociatív. Vagy dönthet a fordító úgy, hogy a magasabb precedenciájú kifejezéseket akármilyen sorrendben értékelteti ki futásidőben, s majd a részeredmények felhasználásával lesz az értékadás jobbról balra? Mert én úgy gondoltam, amikor ezt a sort leírtam, hogy előbb meghatározza p[j] értékét, majd utána ezt értékül adja buff[j]-nek, majd j-t növeli eggyel.

Ezt a warningot egyébként a Qt Creator zúdítja rám. Miért nem mcedit-tel írom a forráskódot? Akkor boldog tudatlanságban élhetnék... :)

Hozzászólások

Szerkesztve: 2025. 05. 20., k – 16:37

>Ezt a warningot egyébként a Qt Creator zúdítja rám.

Nem a fordítóból veszi? Saját értelmezője és warningjai vannak? Nem hinném. Nézz utána, hogy milyen parancsot futtat, gondolom szigorúbb warningokat kér magától, mint ahogy te szoktad paraméterezni a fordítót.

IMHO ez a j++ indexben már önmagában is zavaró, én a falra mászok ezektől. Nálam ez így nézne ki: {buff[j] = p[j]; j++;} Minek terheljem az olvasót azzal, hogy akkor ez posztfix, tehát kiértékelés után lesz inkrementálva és satöbbi? Leírnám úgy ahogy történik sorban és kész. Ezeket már tényleg kibogozza a fordító optimálisra akárhogy is írod az ekvivalens kifejezéseket.

Igazából az a kérdésem, hogy ez a sor egyértelmű a C-ben, vagy a fordítható fordíthatja-e úgy, hogy az értékadás bal oldalával foglalkozik előbb, ott inkrementálja az indexet, majd a jobb oldal ezt a növelt értéket használja. Szerintem ezt nem teheti a fordító - ebben tévedhetek -, egyértelműnek és jónak látom ezt a sort. Azokkal itt nem kívánok foglalkozni, akik kényszeresen kiteszik oda is a zárójelet, ahova nem kell, hátha a fordító rosszul emlékszik a precedenciára, és hasonlók. A mask << x + 4 is egyértelmű, de ha valaki zárójel fetisiszta, az írhatja felőlem, hogy mask << (x + 4), csak ne szaladjunk abba bele, hogy muszáj, mert biztos bugos a fordító, vagy annak a feje, aki olvassa a kódot.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

>Szerintem ezt nem teheti a fordító - ebben tévedhetek -, egyértelműnek és jónak látom ezt a sort.

>Azokkal itt nem kívánok foglalkozni, akik kényszeresen kiteszik oda is a zárójelet, ahova nem kell, hátha a fordító rosszul emlékszik a precedenciára, és hasonlók.

Az a baj, hogy aminek egyértelműnek kellene lenni szerinted - nevezetesen, hogy mi a kiértékelési sorrend - az a jelek szerint nem is egyértelmű a szabvány szerint. (Én se tudtam.) Ezért mondom, hogy mindenki sokkal jobban jár, ha sorba le van írva, hogy mit kell csinálni. Fel se merülne a probléma, ha az inkrementálás külön sorban lenne leírva úgy, ahogy ésszerű volna.

Persze a C nyelv egy trükkhalmaz, még akkor is megviccelheti az embert, ha mindent háromszor körüljár. De ésszerűbb legalább a triviális komplexitást elkerülni. Az olyanokat, mint például ez, hogy indexben inkrementáljuk a változót. Szép trükkös, ismerem én is az egysorosokat, de már nem írok le ilyeneket többé. Jobb a békesség.

Az indexben inkrementálással nincs baj, itt a gond abból lehet, hogy ezt az indexet máshol is felhasználom, s kérdés, az még az inkrementálás előtt vagy után történik-e. Az asszociativitásból az jönne, hogy előbb, de valóban, ahogy NevemTeve írta is, lehet ezt úgy fordítani, hogy rossz legyen. Ugye, lehet ilyet is csinálni:

a = b = c = 5;

Ha nem lehetne használni az indexben inkrementálást, akkor felesleges lenne a pre- és postincrement. Azért van, hogy használjuk. Engem az lepett meg, hogy van arra esély, hogy ez úgy forduljon le, hogy rossz legyen.

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE

buff[j++] = p[j]

A derék fordító maga dönthet arról, hogy ebből mit generál:
#1:

char *tmp= &buff[j];
++j;
*tmp = p[j]

#2:

buff[j] = p[j];
++j;

A jövőálló megoldás nyilván két index használata:


k= j;
while (isupper((unsigned char) p[j])) {
   buff[k++] = p[j];
}

 

Ha mondjuk kiderül, hogy az elején lévő számjegyeket át kell lépni:


k= j;
while (isdigit((unsigned char) p[j])) ++j;
while (isupper((unsigned char) p[j])) {
   buff[k++] = p[j];
}

 

#1 egy reális veszély? Azért nyomasztó, mert néhány helyen használtam ilyesmit kódban, s elég kellemetlen nagyon sok tízezer sorban az összes ++-ra keresni, s egyesével átnézni. Abból indultam ki, hogy az értékadás miatt előbb lesz kiértékelve a jobb oldal, s csak utána a bal, mert ez a #2, s akkor jó a kód.

Szerk.: Abban lehet bízni, hogy egy adott fordító legalább következetesen #2-t fordítja minden hasonló esetben? Vagy kétségbeesetten kezdjem felkutatni azt a kevés helyet a jó nagy kódban, ahol ilyen van?

tr '[:lower:]' '[:upper:]' <<<locsemege
LOCSEMEGE