The documentation here has a detailed explanation.
To be able to traverse these relationships for standard objects, a
relationship name is given to each relationship. The form of the name
is different, depending on the direction of the relationship:
For child-to-parent relationships, the relationship name to the parent is the name of the foreign key, and there is a relationshipName
property that holds the reference to the parent object. For example,
the Model child object has a child-to-parent relationship to the
Widget object, so the value of relationshipName in Contact is
Widget__r. These relationships are traversed by specifying the parent
using dot notation in the query, for example:
SELECT Model__c.Name, Model__c.Widget__r.Name from Model__c
This query returns the names of all the Models in the organization, and for each Model, the Widget name associated with
(parent of) that Model.
For parent-to-child relationships, the parent object has a name for the child relationship that is unique to the parent, the plural of
the child object name. For example, Widget has a child relationship to
Models and has a relationshipName for them called Models. These
relationships can be traversed only in the SELECT clause, using a
nested SOQL query. For example:
SELECT Widget__c.Name, (SELECT Model__c.Name FROM Widget__c.Models__r) FROM Widget__c
This query returns all Widgets, and for each Widget, the name of each Model associated with (the child of) that Widget.