- am urmatoarele instructiuni : i=10;
buffer = (char*) malloc (i+1);
printf("\n %d\n", sizeof(buffer));
Instructiunea malloc() din cate stiu aloca in memoria heap n octeti. In cazul de fata cand vreau sa afisez dimensiunea zonei de memorie alocata cred ar trebui sa imi afiseze, presupun 11 octeti. Mie imi afiseaza 4 octeti.
Operatorul sizeof() îţi spune într-adevăr dimensiunea argumentului. Dar în cazul de faţă argumentul este un pointer către zona de memorie alocată dinamic (nu este o variabilă alocată static). Deci e normal ce se întâmplă -- îţi întoarce doar spaţiul necesar pentru a stoca un pointer (întrucât rezultatul e 4, presupun că ai un SO pe 32 de biţi, sau oricum, spaţiul de adrese disponibil pentru fiecare proces e de 32 de biţi). Sintaxa e ce-i drept derutantă -- arată ca o funcţie, dar nu este. E un operator unar iar expresia sizeof(buffer) se evaluează la compilare.
Poţi să obţii dimensiunea zonei de memorie alocate ca (i + 1) * sizeof(char) (i.e. ai alocat spaţiu pentru i + 1 elemente de tip char).
Edit: acum pentru a doua întrebare

.
Hai să ne uităm întâi pe ce ar trebui să facă strstr:
NAME
strstr, strcasestr - locate a substring
SYNOPSIS
#include <string.h>
char *strstr(const char *haystack, const char *needle);
#define _GNU_SOURCE
#include <string.h>
char *strcasestr(const char *haystack, const char *needle);
DESCRIPTION
The strstr() function finds the first occurrence of the substring nee‐
dle in the string haystack. The terminating '\0' characters are not
compared.
The strcasestr() function is like strstr(), but ignores the case of
both arguments.
RETURN VALUE
These functions return a pointer to the beginning of the substring, or
NULL if the substring is not found.
Prin urmare, apelul:
pdest=strstr(string, str);
va întoarce un pointer la începutul primei apariţii a lui "este" din "Primul pas este cel mai greu".
Pe sistemul meu s-a nimerit sa iasă aşa:
(gdb) p &string[0]
$1 = 0x7fffffffe260
(gdb) p pdest
$2 = 0x7fffffffe26b
Adică: string este reţinut în memorie începând cu adresa 0x7fffffffe260 (acolo se află caracterul 'P' -- după el urmează celelalte, consecutiv), iar pdest reţine valoarea 0x7fffffffe26b, arătând astfel că prima apariţie a lui "este" începe de la acea adresă.
Acuma, scăzând din pdest adresa primului element din pstr, vom obţine numărul de caractere dintre începutul şirului şi prima apariţie a lui este.
Totuşi, două comentarii cu privire la:
(int)(pdest-string + 1)
Codul ăsta nu e bun

.
În primul rând, cine îl citeşte va presupune că string e un pointer spre o zonă de memorie alocată dinamic; desigur că îşi va da seama ca nu e aşa (definiţia e câteva rânduri mai sus), dar consistenţa ajută foarte mult la urmărirea codului, pentru că nu trebuie să te uiţi de fiecare dată la declaraţia variabilelor. Chiar dacă şi aşa cum e scris acolo e corect sintactic, recomandarea mea când ai de scăzut două adrese e să arăţi asta explicit -- i.e. prin &pstring[0]. Asta funcţionează folosind operatorul & (care se evaluează la adresa argumentului său) către elementul pstring[0] -- se citeşte chiar aşa, "adresa lui pstring[0]") şi are avantajul de a arăta imediat celui care citeşte codul că scazi două adrese, dintre care a doua e către primul element al unui array alocat static.
În al doilea rând (şi de fapt de-asta codul nu e bun), codul face presupunerea implicită că o variabilă de tip char are un octet (motiv din care se presupune că dacă scazi cele două adrese şi îţi iese diferenţa în bytes, sunt exact atâtea caractere câţi bytes sunt). Tradiţional, un char chiar are 1 byte, dar standardul C nu cere lucrul ăsta în mod explicit, deci nu e bine să te bazezi pe el.