├── 001_value_semantics.md ├── 002_pointers.md ├── 003_compiletime_vs_runtime.md └── LICENSE /001_value_semantics.md: -------------------------------------------------------------------------------- 1 | Value semantics is one of the core principles of C and C++ 2 | 3 | I would even go so far as to say that this is the most important part of C++ in terms of its design. 4 | 5 | In the following discussion, I will ignore everything in the language that lets you bypass the value semantics. You have to learn the rules before you understand why and where thy can or should be bypassed. The less you bypass it, the more robust and efficient and idiomatic your program gets. 6 | 7 | --- 8 | 9 | **Types** 10 | 11 | Every C++ type (Lets ignore void for now) is considered to be a string of bits of certain size. 12 | Practically speaking, the granularity is usually at the byte level and a byte is defined as a certain number of bits ( typically 8 ). We will not go into the pedantics of uncommon and obsolete systems which use 6 bits per byte or other such quirks. 13 | 14 | Every type has a certain set of operators defined on it, and most operators can be overloaded for all types. 15 | The few ones that you cannot override are: 16 | 17 | - :: or the scope resolution operator 18 | - ?: or the ternary operator 19 | - dot operator ( this will change soon) 20 | 21 | --- 22 | 23 | **Values** 24 | 25 | There are many academic CS discussions as to what exactly a value is - the simple way to think of it is that a value is an actual string of bits residing in physical memory or some hardware element like a register or even I/O port 26 | 27 | Physical memory does not really have a notion of types - all it has is the ability to treat 1 or more bytes as a unit of computation. Our beloved x86_64 processors can treat a location in memory as 1, 2, 4, 8 byte integers (and even 128, 256, 512 as SIMD, but that's irrelevant here) 28 | 29 | In C++, there are two kinds of values : r-values and l-values 30 | 31 | - l-values have a program visible address in memory where they live, and have a lifetime. l-values often have a name, but not always. 32 | - r-values are temporary things that cease to exist past the expression in which they appear 33 | 34 | ``` 35 | int x = 10; // x is l-value, 10 is r-value 36 | int arr[10]; 37 | arr[2] = 1; // arr[2] is the l-value 38 | ``` 39 | 40 | The predefined operators for all types work in the same way. 41 | Aggregate objects like structs are values too. 42 | 43 | ``` 44 | struct Point 45 | { 46 | int x, y; 47 | } 48 | ``` 49 | 50 | This is treated as a chunk of memory that is >= sizeof(int) * 2 51 | 52 | *[Note]* 53 | 54 | C arrays are a historical glitch in the design of the language, and they break this rule of treating all values in the same way. For now ignore C based arrays, we will deal with them later and if possible rarely ever use them in our code. The semantics of C arrays are the biggest screw up of the language, that we have to live with today, because it's too late to change things. 55 | 56 | --- 57 | 58 | **Value semantics in assignment** 59 | 60 | When a value is assigned to another, a bit identical copy is made from the source memory to the destination memory. This is fundamental. 61 | 62 | If you write : 63 | ```x = y;``` 64 | And x and y are the same type and the = operator is not overloaded, after this statement, it means that the memory at the place where x resides is bit for bit identical with that where y resides, upto sizeof(x) bytes. 65 | There are no exceptions to this rule (except for the array snafu) 66 | 67 | This is not true of any other mainstream language as far as I know (perhaps traditional Pascal ) 68 | 69 | Value semantics means that two names can never refer to the same block of memory (we will see how to bypass value semantics when really needed) 70 | 71 | --- 72 | 73 | **Value semantics in function calls** 74 | 75 | ``` 76 | int fn(int y) 77 | { 78 | y++; 79 | return y; 80 | } 81 | 82 | int x = 10; 83 | int z = fn(x); 84 | ``` 85 | 86 | When fn(x) is called, an independent copy of x is created, and that is the object called y inside of the function. 87 | 88 | Once again there is no exception to this rule (except for C arrays - O GOD WHY!) 89 | 90 | --- 91 | 92 | **The value of value semantics** 93 | 94 | In almost all languages, the lifetime of an object depends on the lexical scoping of its name. 95 | If a variable name is visible, the contents of that variable had better be accessible and alive in memory - this is common sense. 96 | 97 | In C++ we have several scopes: 98 | Global scope - the names of these are either visible in the file they are declared, or across the entire program (using extern) 99 | Function and block scope - whenever you see a pair of braces {} - a new scope exists. Names defined within that {} are not visible outside of it. 100 | Class/Struct scope - The names of members inside a class are visible inside its methods and they are also visible within the scope where a value of that class has its own name. Classes can define more classes within them and the same rules apply. 101 | 102 | You can see that scopes form a tree hierarchy of visibility of names. 103 | 104 | Objects' memory is allocated when you declare them, and the memory is reclaimed when the object goes out of scope - obviously, if the name of a variable "expires", that memory is no longer reachable in the program, so it must be reclaimed. 105 | 106 | Since scope is a tree, it should be clear that no variable in an intermediate scope ever dies before one in a deeper scope. Therefore, memory is always allocated and deallocated in a LIFO (last in first out) manner. 107 | 108 | If y was declared and x was declared, x has to die before y. This is unconditional. 109 | LIFO structude automatically(pun intended) means that a stack can be used to store all the values in your program (except the outermost scope, we will ignore that for now) 110 | 111 | A stack is the most efficient memory allocation strategy that can ever exist. Allocation is one increment instruction, deallocation is one decrement instruction. 112 | 113 | The LIFO lifetime of allocated variables also ensures that no memory is ever left hanging for even 1 cycle more than it needs to. 114 | 115 | --- 116 | 117 | **Use value semantics everywhere** 118 | 119 | Any data type or object you design must adhere to value semantics, like the rest of the language. 120 | You can see the extreme application of value semantics in pure functional languages, where all objects are immutable, and can only modified by creating a new copy. 121 | 122 | Some quite famous libraries like OpenCV break this fundamental paradigm of C++ 123 | 124 | ``` 125 | cv::Mat x = somehowCreateMat(); 126 | cv::Mat y = x; 127 | // Now x and y refer to the same location in memory 128 | ``` 129 | 130 | This is a horrible horrible mistake and unless you have some really really great reasons to, you should never make your objects behave like this in C++. 131 | 132 | In the next post we will explore pointers, the first tool that lets you control value semantics in a consistent way, and start understanding "No sidewheels/ninja mode". 133 | 134 | Later we will explore references, classes, move semantics, smart pointers etc. and how we can preserve value semantics externally and keep our programs fast and robust, while still breaking the rules inside the implementations. 135 | -------------------------------------------------------------------------------- /002_pointers.md: -------------------------------------------------------------------------------- 1 | **Pointer semantics** 2 | 3 | Life would be really simple if we could live with only values. The world works like that if you exclude language - there are things... and that's it. Functional languages "work" like this, but ironically are far removed from the real world. 4 | 5 | In software, as opposed to the world, a given thing often needs to have multiple names - or rather, two or more names refer to the same thing. This requirement was referred to as "reference semantics" in older languages. 6 | 7 | -- 8 | 9 | **The core problem** 10 | 11 | Functions need to be able to modify their parameters in a way that's visible to the caller - let's follow the common sense reasoning why this came into being. 12 | The first lessons programmers learned was to never repeat code - so instead we put repeating code into a thing called a procedure, and just used the name of the procedure when we needed that code to repeat. 13 | There are three kinds of chunks of code that you can convert to a procedure and simplify a longer bot of code. 14 | 15 | - The simplest kind is code that is context free like ```PRINT "HELLO"``` - that's easy - plain text substitution or macros can do that. 16 | - The next kind is code that operates on one or more values and returns another value like ```sqrt()``` and so forth - this is similar to the defintion of function in math 17 | - To make it universal, the third kind is needed, where a chunk of code can refers to many variables in its lexical scope, and you want to extract it into a reusable procedure. The procedure needs some way of being able to _refer_ to and modify the values in the lexical scope where it is invoked. To this end, reference parameters are the first solution. 18 | 19 | In C however, everything is a value, and we're loath to give up that notion. 20 | If a parameter is passed to a function and the function has to modify it so the caller sees the change, then the function needs to know information privy to the caller - as to where that original variable exists in memory. 21 | 22 | That "where something exists in memory" is nothing but the hardware concept of adresses. Addresses are nothing fancy, just think of them as an integer index into the entire adressable memory of the system. 23 | C, being a "high level assembler" killed two birds with one stone, by using addresses - For one, you could do low level memory access, and then you could also pass addresses of values to functions, as values in turn and get reference like semantics without messing up the value semantics we had. 24 | 25 | -- 26 | 27 | **Pointers** 28 | 29 | A pointer is typically an integral typed value, which represents an address in memory. 30 | A pointer is always associated with another type - we say "Pointer to (type) T" or ```T*```. 31 | A pointer itself is a value that has the similar semantics as say integers. 32 | Since a pointer is a value type variable, it can itself be a type pointed to - so we can have pointer to pointer to T - ```T**``` and so on ad infinitum 33 | 34 | C supports the following pointer operations: 35 | - Dereference with the * operator: evaluate the contents at the address in the pointer as an r-value of type T 36 | - Perform + and - operations on the address stored in the pointer variable. 37 | - Retrieve the memory address of a variable with the & operator. 38 | 39 | All pointers to data types have the same size - this is obvious since all pointers are memory addresses. 40 | Even though pointers are like simple memory indices, pointers to different types may not be compatible. 41 | This is because of hardware memory implementation limitations. 42 | 43 | For example (assuming 4 byte integers): 44 | ``` 45 | char x[] = {'H', 'a', 'h', 'a'}; //This variables value is at an address which is aligned to a level needed by char 46 | int *px = (int *)&x; // We just forced the compiler to let us treat that value as a 4 byte integer 47 | 48 | // The following is undefined - we cant say if the hardware can read a 4 byte integer at that address 49 | // Perhaps the address is not at an alignment that is OK for reading an int. A hardware exception (or TRAP) may occur 50 | cout << *px << endl; 51 | ``` 52 | 53 | You can always reinterpret cast any ```T*``` as a ```char*``` and you can also store any ```T*``` inside a ```void*``` 54 | 55 | C allows you to assign a ```void*``` to ```T*``` but C++ does not - you have to explicitly cast it. 56 | 57 | -- 58 | 59 | **Iterators** 60 | 61 | This is a good time to diverge into an iterators, briefly. 62 | An iterator is the generalized version of what a pointer is - just like pointers, iterators support the following ops 63 | - Dereference with the * operator: evaluate the contents that the iterator points to as an r-value of type T 64 | - Perform some arithmetic 65 | - ForwardIterators support ++ 66 | - BidirectionalIterators support ++ and -- 67 | - RandomAccessIterators support + and - 68 | - OutputIterators work like output streams - you can only advance them after writing (dereference) 69 | 70 | Every pointer is an iterator. 71 | 72 | -- 73 | 74 | **Arrays and Pointers - The ugliest part of C** 75 | 76 | C was written to be as close to the metal as possible. So they discarded all notions of runtime checking of any operation - whether it's integer overflow, accessing inacessible memory or dividing by 0, there is never any code generated to check this at runtime. 77 | 78 | Almost all other languages do this, at a very, very high runtime cost. 79 | 80 | Since we only wanted the fastest thing rather than the safest, C arrays have no size information tacked to them. A C array is just a chunk of memory. The compiler knows its size when it was declared, but for the most part ignores that in any generated code. 81 | You can ask for an arrays byte size with ```sizeof(arr)``` and get the length with ```sizeof(arr)/sizeof(arr[0])``` 82 | 83 | Remember that ```sizeof``` is a compiletime operator - it's like a macro that evaluates to an actual constant. 84 | As long as that array variable was in scope, ```sizeof``` works. 85 | 86 | 87 | Now all this would be perfectly fine, except that if we need to pass arrays as parameters to functions, then we have a problem. 88 | An array is only its contents, there is no size info, so if we pass those values to a function, the function cannot know where the array ends. 89 | If it cannot know where it ends, you cannot keep any parameter in memory after the array parameter (including another array), so that seems like a big limitation. Remember that during runtime, all variables are only addresses offset from some base. 90 | 91 | The "solution" was to say that when you have ```int arr[10];``` then when you write just ```arr```, the compiler treats it as ```&(arr[0])```. 92 | Meaning that the name of an array when used outside of its declaration, _decays_ to a pointer to its first element. 93 | 94 | Now we can happily pass any number of array and other parameters to a function and it's up to the programmer to ensure that they pass the size also along so we can iterate over that array safely. 95 | 96 | The nasty side effect of this is that we lost value semantics, but also that it is not at all obvious. 97 | If we saw the following code: 98 | ``` 99 | int fn(int a[10]) 100 | { 101 | int i; 102 | for(i = 0; i < 10; ++i) 103 | { 104 | printf("%d : %d\n", i, a[i]); 105 | } 106 | 107 | return a[9]; 108 | } 109 | ``` 110 | 111 | The common sense guy might think - Oh well, this function is constrained to accept only int arrays of length 10. 112 | 113 | But then this code compiles without any complaint: 114 | 115 | ``` 116 | int main() 117 | { 118 | int k[5] = {1, 2, 3, 4, 5}; 119 | return fn(k); 120 | } 121 | ``` 122 | 123 | ```fn(k)``` looks like were passing some data as a value, and that data seems to be an array. But actually were not passing that array. We are passing a pointer to the start of the array, and so the nice world of value semantics is doomed. 124 | 125 | We might have as well declared fn as ```int fn(int *a)``` and it would make no difference to the meaning of the program 126 | 127 | 128 | The best advice to any C++ programmer is : 129 | - Use a ```std::array``` rather than a C array 130 | - If not, use a ```std::vector``` 131 | - If you do use a C array, never pass it as a parameter 132 | 133 | There is just too much bad code and resulting grief from using C array parameters. Don't do it in C++! 134 | 135 | -- 136 | 137 | **Valid uses of pointer semantics** 138 | 139 | Alexander Stepanov says that the acid test for any language is whether you can write a totally generic ```swap``` function in it. 140 | How's that for C++ love eh? 141 | 142 | You can ponder that and check if your favorite language can do that simply, but in any case, in the C world, the only way to make a function mutate its arguments is by passing pointers to them. 143 | 144 | There are two legit uses for pointers passed to functions : 145 | - Passing a pointer to a large object to avoid copying it, like a struct or a buffer (as long as you pass the size with it) 146 | - Passing a pointer to something that the function modifies 147 | 148 | If you follow a couple of simple rules when using pointers, you can mostly avoid the perils 149 | - Never return a pointer from a function 150 | - Never pass a pointer to a function whose pointee type (and size) is unknown to the function 151 | 152 | There are rationalizations for these recommendations: 153 | - One must always make sure that a pointer does not outlive the thing it points to - passing a pointer out from a function does just that. Even if it is dynamically allocated memory, you just bought yourself potential trouble at a discount. If pointers are passed into functions but not out, then they always point to stuff that outlives them. 154 | - Passing a pointer to a buffer/array is a prime candidate for messing up - as we discussed above. Pointers to primitive types and structs have some safety, as opposed to array pointers. 155 | 156 | 157 | These rules are impossible to follow always in plain C, thus the language is inherently unsafe. 158 | However in C++ we need not get into this C cesspool unless we really need to. 159 | 160 | 161 | References, smart pointers, templates and so on can let us avoid this nastiness, as we will explore in the forthcoming posts. 162 | 163 | 164 | -- 165 | 166 | -------------------------------------------------------------------------------- /003_compiletime_vs_runtime.md: -------------------------------------------------------------------------------- 1 | ## Compiletime versus runtime 2 | 3 | It's very important to realize what part of your code is instructions to your compiler and what part becomes instructions to the computer. 4 | 5 | A proper understanding of this is essential to reading and writing C++ code. 6 | 7 | --- 8 | 9 | **Compile time** 10 | 11 | - **Constants** - Any arithmetic operation involving constants gets converted to a constant by the compiler. 12 | 13 | ```int a = 512 * 1024; // a gets 524288 ``` 14 | 15 | - **sizeof()** - sizeof evaluates only the type of the expression you pass it. It does not cause any code to be generated at runtime 16 | 17 | ``` 18 | int x = sizeof(int); 19 | int *px = NULL; 20 | int y = sizeof(*px); // pf is NOT dereferenced at runtime 21 | ``` 22 | 23 | - **:: operator** - This is a merely a hint to the compiler as to which scope to look for a symbol in 24 | 25 | - **\# preprocesor directive** - This happens way before the compiler even touches the code - text subsitution and arithmetic only 26 | 27 | - **templates** : templates are 100% compiletime - when a template is instantiated, it serves as instructions to the compiler to generate code internally based on the template declaration. 28 | 29 | - **lambdas** : Again these are syntactic sugar over function objects, so a lambda is instructions to the compiler to generate a class with an overloaded () operator. The body of lambdas is of course runtime code. 30 | 31 | --- 32 | 33 | **Both Compile and Runtime** 34 | 35 | - **The & reference operator** : When you use a reference to alias a variables name, the compiler generates no extra code for this. When you use a reference as a parameter or return value, it works as though you used a pointer and runtime semantics are involved 36 | ``` 37 | int a = 1; 38 | int &b = a; // No code is actually generated here, b is just another name for a during compiletime 39 | ``` 40 | 41 | 42 | - **The dot and arrow operators** : The right hand side of the dot operator is a symbolic name that only exists at compile time. It does lead to code generation in the sense that the compiler calculates the addresses of member variables by adding a fixed offset, but it is irrelevant to the runtime state of the application. If the standard implements the proposal to allow overloading of this operator, it can lead to an actual function call at runtime. 43 | The arrow operator works in a similar fashion to the dot operator, it may involve dynamic polymorphism, since the exact type of the object upon which it is being called can vary at runtime. The dot operator can also act the same way, if we use references. In the cases where the compiler can determine the type of the object at compiletime, extra code is not generated 44 | 45 | - **The & addressof operator** : During runtime there are no variable names, so the meaning of & being "give me the address of a variable" is meaningless. But it still has the meaning "give me the address of this l-value". Obviously r-values may or may not be actually present in actual memory, whilst l-values always can be assumed to be in some storage (except if they are optimized away). So & is somewhat of a hybrid operator, tending to be more compiletime than runtime. 46 | 47 | - **constexpr** : constexpr is the new const - A constexpr expression or function is attempted to be evaluated at compile time, and if successful, it becomes a compile time hardcoded value. If the compiler finds that it cannot do the computation at compiletime, it adds a runtime code to do it. 48 | For example: 49 | ``` 50 | constexpr int sum(int x, int y) 51 | { 52 | return x+y; 53 | } 54 | 55 | 56 | int main(int argc, char **argv) 57 | { 58 | constexpr int i = sum(10, 10); 59 | int j = sum(argv[0][0], argv[0][1]); 60 | 61 | return i + j; 62 | } 63 | ``` 64 | In the above code, i gets assigned the constant 20 directly while the j initialization causes the compiler to add a function call. If j was declared constexpr, the compielr complains that the value is not known at compile time. 65 | 66 | - OO and dynamic dispatch - When you have static polymorphism, any method call is merely a plain function call. When it is dynamic, there are layers of indirection added for the code to determine the runtime type of the object. 67 | 68 | 69 | 70 | Almost everything else in C++ is runtime semantics. 71 | 72 | --- 73 | 74 | When you look at a line of code, just ask yourself this question : 75 | 76 | _Can the meaning of this change based on the runtime state of the program at this point or not?_ 77 | 78 | If the answer is yes then its a runtime construct, otherwise it is a compiletime construct. Remember that any constant, constexpr variable or function is (and must be known) at compiletime. 79 | 80 | The more stuff you do at compiletime (including code generation via macros or templates), the less you rely on work done at runtime and possibly make your program faster. 81 | 82 | For example C++ ```std::sort()``` can always be faster than C ```qsort()``` because ```qsort()``` uses a runtime parameter as the comparision function, and that function is called umpteen zillion times. 83 | 84 | The C++ sort takes a comparision object, which can be a lambda/template/inline function, which inlines its code right within the sort template function. 85 | 86 | No unnecessary function calls. 87 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | CC0 1.0 Universal 2 | 3 | Statement of Purpose 4 | 5 | The laws of most jurisdictions throughout the world automatically confer 6 | exclusive Copyright and Related Rights (defined below) upon the creator and 7 | subsequent owner(s) (each and all, an "owner") of an original work of 8 | authorship and/or a database (each, a "Work"). 9 | 10 | Certain owners wish to permanently relinquish those rights to a Work for the 11 | purpose of contributing to a commons of creative, cultural and scientific 12 | works ("Commons") that the public can reliably and without fear of later 13 | claims of infringement build upon, modify, incorporate in other works, reuse 14 | and redistribute as freely as possible in any form whatsoever and for any 15 | purposes, including without limitation commercial purposes. These owners may 16 | contribute to the Commons to promote the ideal of a free culture and the 17 | further production of creative, cultural and scientific works, or to gain 18 | reputation or greater distribution for their Work in part through the use and 19 | efforts of others. 20 | 21 | For these and/or other purposes and motivations, and without any expectation 22 | of additional consideration or compensation, the person associating CC0 with a 23 | Work (the "Affirmer"), to the extent that he or she is an owner of Copyright 24 | and Related Rights in the Work, voluntarily elects to apply CC0 to the Work 25 | and publicly distribute the Work under its terms, with knowledge of his or her 26 | Copyright and Related Rights in the Work and the meaning and intended legal 27 | effect of CC0 on those rights. 28 | 29 | 1. Copyright and Related Rights. A Work made available under CC0 may be 30 | protected by copyright and related or neighboring rights ("Copyright and 31 | Related Rights"). Copyright and Related Rights include, but are not limited 32 | to, the following: 33 | 34 | i. the right to reproduce, adapt, distribute, perform, display, communicate, 35 | and translate a Work; 36 | 37 | ii. moral rights retained by the original author(s) and/or performer(s); 38 | 39 | iii. publicity and privacy rights pertaining to a person's image or likeness 40 | depicted in a Work; 41 | 42 | iv. rights protecting against unfair competition in regards to a Work, 43 | subject to the limitations in paragraph 4(a), below; 44 | 45 | v. rights protecting the extraction, dissemination, use and reuse of data in 46 | a Work; 47 | 48 | vi. database rights (such as those arising under Directive 96/9/EC of the 49 | European Parliament and of the Council of 11 March 1996 on the legal 50 | protection of databases, and under any national implementation thereof, 51 | including any amended or successor version of such directive); and 52 | 53 | vii. other similar, equivalent or corresponding rights throughout the world 54 | based on applicable law or treaty, and any national implementations thereof. 55 | 56 | 2. Waiver. To the greatest extent permitted by, but not in contravention of, 57 | applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and 58 | unconditionally waives, abandons, and surrenders all of Affirmer's Copyright 59 | and Related Rights and associated claims and causes of action, whether now 60 | known or unknown (including existing as well as future claims and causes of 61 | action), in the Work (i) in all territories worldwide, (ii) for the maximum 62 | duration provided by applicable law or treaty (including future time 63 | extensions), (iii) in any current or future medium and for any number of 64 | copies, and (iv) for any purpose whatsoever, including without limitation 65 | commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes 66 | the Waiver for the benefit of each member of the public at large and to the 67 | detriment of Affirmer's heirs and successors, fully intending that such Waiver 68 | shall not be subject to revocation, rescission, cancellation, termination, or 69 | any other legal or equitable action to disrupt the quiet enjoyment of the Work 70 | by the public as contemplated by Affirmer's express Statement of Purpose. 71 | 72 | 3. Public License Fallback. Should any part of the Waiver for any reason be 73 | judged legally invalid or ineffective under applicable law, then the Waiver 74 | shall be preserved to the maximum extent permitted taking into account 75 | Affirmer's express Statement of Purpose. In addition, to the extent the Waiver 76 | is so judged Affirmer hereby grants to each affected person a royalty-free, 77 | non transferable, non sublicensable, non exclusive, irrevocable and 78 | unconditional license to exercise Affirmer's Copyright and Related Rights in 79 | the Work (i) in all territories worldwide, (ii) for the maximum duration 80 | provided by applicable law or treaty (including future time extensions), (iii) 81 | in any current or future medium and for any number of copies, and (iv) for any 82 | purpose whatsoever, including without limitation commercial, advertising or 83 | promotional purposes (the "License"). The License shall be deemed effective as 84 | of the date CC0 was applied by Affirmer to the Work. Should any part of the 85 | License for any reason be judged legally invalid or ineffective under 86 | applicable law, such partial invalidity or ineffectiveness shall not 87 | invalidate the remainder of the License, and in such case Affirmer hereby 88 | affirms that he or she will not (i) exercise any of his or her remaining 89 | Copyright and Related Rights in the Work or (ii) assert any associated claims 90 | and causes of action with respect to the Work, in either case contrary to 91 | Affirmer's express Statement of Purpose. 92 | 93 | 4. Limitations and Disclaimers. 94 | 95 | a. No trademark or patent rights held by Affirmer are waived, abandoned, 96 | surrendered, licensed or otherwise affected by this document. 97 | 98 | b. Affirmer offers the Work as-is and makes no representations or warranties 99 | of any kind concerning the Work, express, implied, statutory or otherwise, 100 | including without limitation warranties of title, merchantability, fitness 101 | for a particular purpose, non infringement, or the absence of latent or 102 | other defects, accuracy, or the present or absence of errors, whether or not 103 | discoverable, all to the greatest extent permissible under applicable law. 104 | 105 | c. Affirmer disclaims responsibility for clearing rights of other persons 106 | that may apply to the Work or any use thereof, including without limitation 107 | any person's Copyright and Related Rights in the Work. Further, Affirmer 108 | disclaims responsibility for obtaining any necessary consents, permissions 109 | or other rights required for any use of the Work. 110 | 111 | d. Affirmer understands and acknowledges that Creative Commons is not a 112 | party to this document and has no duty or obligation with respect to this 113 | CC0 or use of the Work. 114 | 115 | For more information, please see 116 | 117 | --------------------------------------------------------------------------------