<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Shreyash Rai — #c++</title><description>Everything tagged “c++”.</description><link>https://shreyashrai.com</link><item><title>size_t is unsigned, so counting down past zero wraps around</title><link>https://shreyashrai.com/til/cpp-size-t-underflow</link><guid isPermaLink="true">https://shreyashrai.com/til/cpp-size-t-underflow</guid><pubDate>Fri, 03 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I had a loop that walked a vector backwards and it never terminated. The bug is
that &lt;code&gt;size_t&lt;/code&gt; is &lt;strong&gt;unsigned&lt;/strong&gt;, so it can never be negative — subtracting past
zero wraps to a huge positive number instead.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// Broken: when i == 0, --i wraps to SIZE_MAX, so i &amp;gt;= 0 is always true.
for (size_t i = v.size() - 1; i &amp;gt;= 0; --i) {
    use(v[i]);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The same trap hides in any &lt;code&gt;v.size() - 1&lt;/code&gt; when the vector is empty: &lt;code&gt;0u - 1&lt;/code&gt;
is &lt;code&gt;SIZE_MAX&lt;/code&gt;, not &lt;code&gt;-1&lt;/code&gt;, so a &quot;last index&quot; computed that way points way off the
end.&lt;/p&gt;
&lt;p&gt;One fix is to offset the index by one and count the &lt;em&gt;other&lt;/em&gt; variable down, so
the loop variable stays in valid unsigned territory:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// Fixed: i is the count remaining; the real index is i - 1.
for (size_t i = v.size(); i &amp;gt; 0; --i) {
    use(v[i - 1]);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The general rule: if a value can go negative, don&apos;t store it in an unsigned
type. Reach for a signed index (or C++20&apos;s &lt;code&gt;std::ssize&lt;/code&gt;) when you need to count
below zero.&lt;/p&gt;
</content:encoded><category>c++</category><category>gotchas</category></item><item><title>Linked Lists</title><link>https://shreyashrai.com/til/linked-lists</link><guid isPermaLink="true">https://shreyashrai.com/til/linked-lists</guid><pubDate>Mon, 22 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Array stores data in continuous or contiguous memory.&lt;/li&gt;
&lt;li&gt;All accessible in O(1) time, because it directly reaches address of elements inside by simple arithmetic, BECAUSE they are all stored together.&lt;/li&gt;
&lt;li&gt;But, there&apos;s problems with this contiguous memory is that when there&apos;s no space for the next element you must copy the elements to a new location, wasting time.&lt;/li&gt;
&lt;li&gt;That&apos;s why we use linked lists because it stores it&apos;s data in random places of the memory and each are connected.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Linked Lists&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Stores data in Nodes that are spread out in memory but all nodes are storing address of the next node in the list.&lt;/li&gt;
&lt;li&gt;Traversal time complexity: O(n)&lt;/li&gt;
&lt;li&gt;Insertion time complexity: O(n)
&lt;img src=&quot;/public/images/Pasted%20image%2020260622201004.png&quot; alt=&quot;&amp;quot;Meow&amp;quot;&quot; /&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Arrays vs linkedlists&lt;/h2&gt;
&lt;h3&gt;a) Cost of Accessing an element&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Array needs constant time O(1) because simple arithmetic leads to the next element.&lt;/li&gt;
&lt;li&gt;Address of i th element = Base_address + i * Size_of_data_type&lt;/li&gt;
&lt;li&gt;Linked List needs O(n) where is n is number of elements in the list.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;B) Memory Requirement&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Array has a fixed size, so partially filled array takes as much space as it was full.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;So there&apos;s a lot of unused space in memory.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Sometimes, memory may not be available all the time since contiguous memory so it requires copying of data.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Linked List requires extra memory for pointer variables. They are 4 bytes each (in 32bit system). But 8 bytes in 64bit system.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;But it does not leave unused memory.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;It&apos;s usually better than array when the datatype being stored has higher size. But depends on the case on which performs better.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Nodes being stored at random places in memory.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;C) Cost of insertion&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;In the beginning&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Arrays have to shift all elements by one and then insert the value at starting. So O(n)&lt;/li&gt;
&lt;li&gt;Linked List disconnects head node and reattaches new node in the beginning. So O(1)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;In the end&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Arrays: Just insert element at the new free location, or copy into new array if it is full. So O(1) or O(n)&lt;/li&gt;
&lt;li&gt;Linked List needs to traverse until the end then attach new node. So O(n)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;At i-th location (average case)&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Arrays: Shift some elements forward. So O(n)&lt;/li&gt;
&lt;li&gt;Linked list: Traverse i elements, so O(n)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Implementation in both C and C++&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Making a node&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;typedef struct Node{
	int data;
	struct Node* next;
} Node;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;struct Node{
	int data;
	Node* next;
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Initializing Linked List&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Node* A; //initialising empty LL
A = NULL; //Setting it as Null initially
Node* temp = (Node*) malloc(sizeof(struct Node)) //typecasting required, creating a new temporary node
(*temp).data = 2; //Filling data in node
(*temp).next = NULL; //Attaching it to null address
A = temp; //Setting A as temp node
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Node* A;
A = NULL;
Node* temp = new Node();
temp-&amp;gt;data = 2;           // -&amp;gt; is basically short form of the deferencing (*) and accessing structure with .
temp-&amp;gt;next = NULL;
A = temp;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;Node* temp1 = A;
while (temp-&amp;gt;next != NULL){
	temp1 - temp1 -&amp;gt; next;
}

temp = new Node();
temp-&amp;gt;data = 4;
temp-&amp;gt;next = NULL;
temp1-&amp;gt;next = temp;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;#include &amp;lt;stdlib.h&amp;gt;
#include &amp;lt;stdio.h&amp;gt;

typedef struct Node {
	int data;
	struct Node* next;
} Node;

void Insert(Node** pointerToHead, int x);
void Print(Node* head);

int main(){
	struct Node* head = NULL;
	int n,x;
	printf(&quot;Enter number of nodes: &quot;)
	scanf(&quot;%d&quot;, &amp;amp;n);
	for (int i=0; i &amp;lt; n; i++){
		printf(&quot;Enter a number: &quot;);
		scanf(&quot;%d&quot;, &amp;amp;x);
		Insert(&amp;amp;head, x);
		Print(head);
	}
	printf(&quot;\n&quot;);
}

void Insert(Node** pointerToHead, int x){
	Node* temp = (Node*) malloc(sizeof(struct Node));
	temp-&amp;gt;data = x;
	temp-&amp;gt;next = *pointerToHead;
	*pointerToHead = temp;
}

void Print(Node* head){
	while (head != NULL){
		printf(&quot;%d &quot;,head-&amp;gt;data);
		head = head-&amp;gt;next;
	}
	printf(&quot;\n&quot;);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Notes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Node** is a pointer to pointer. Dereferencing it gives us the pointer to a Node. Then we can use -&amp;gt; to grab its data and next&lt;/li&gt;
&lt;li&gt;We used pointer-to-pointer so that we can modify what is at the address of the memory. If we used pointer directly, that would not work because this new argument inside Insert would be a COPY of the pointer and not the one we want to modify.&lt;/li&gt;
&lt;li&gt;Insert function handles both empty and non-empty linked list as if it is empty then head is null which the new temp node takes anyways.&lt;/li&gt;
&lt;li&gt;For C++ we can use classes and the new function (Node* temp = new Node();) for easy.&lt;/li&gt;
&lt;li&gt;This code still doesn&apos;t free up memory.&lt;/li&gt;
&lt;/ul&gt;
</content:encoded><category>C++</category><category>DSA</category></item></channel></rss>